Djmixer
Have you ever want to be a DJ with the minimum of equipments even though you are in your plain room? Well, the project we are working on is exactly what you need!!!!!
This is a project of building DJmixer using raspberry pi with four ultrasonic sensors to playback and loop the music, and change the volumn
To make the experience fit your profile, pick a username and tell us what interests you.
We found and based on your interests.
Have you ever want to be a DJ with the minimum of equipments even though you are in your plain room? Well, the project we are working on is exactly what you need!!!!!
subprocess.hppx-c++hdr - 41.96 kB - 04/14/2019 at 21:49 |
|
|
thread.cppx-c++src - 2.05 kB - 04/14/2019 at 21:49 |
|
|
pi.pdsprjpdsprj - 17.17 kB - 04/14/2019 at 21:49 |
|
|
main.cppx-c++src - 3.97 kB - 04/14/2019 at 21:49 |
|
|
MoodyLoop.wavx-wav - 7.58 MB - 04/08/2019 at 11:43 |
|
check out our test video
Besides the raspberry pi, we design the PCB to transfer data from sensor to pi.
To perform the music in raspberry pi, we apply the ALSA lib in linux to drive the raspi to play and control the music. Details are as following .
int main() {
long loops;
int rc;
int size;
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
unsigned int val;
int dir;
snd_pcm_uframes_t frames;
char *buffer;
/* Open PCM device for playback. */
rc = snd_pcm_open(&handle, "default",
SND_PCM_STREAM_PLAYBACK, 0);
if (rc < 0) {
fprintf(stderr,
"unable to open pcm device: %s\n",
snd_strerror(rc));
exit(1);
}
/* Allocate a hardware parameters object. */
snd_pcm_hw_params_alloca(¶ms);
/* Fill it in with default values. */
snd_pcm_hw_params_any(handle, params);
/* Set the desired hardware parameters. */
/* Interleaved mode */
snd_pcm_hw_params_set_access(handle, params,
SND_PCM_ACCESS_RW_INTERLEAVED);
/* Signed 16-bit little-endian format */
snd_pcm_hw_params_set_format(handle, params,
SND_PCM_FORMAT_S16_LE);
/* Two channels (stereo) */
snd_pcm_hw_params_set_channels(handle, params, 2);
/* 44100 bits/second sampling rate (CD quality) */
val = 44100;
snd_pcm_hw_params_set_rate_near(handle, params,
&val, &dir);
/* Set period size to 32 frames. */
frames = 32;
snd_pcm_hw_params_set_period_size_near(handle,
params, &frames, &dir);
/* Write the parameters to the driver */
rc = snd_pcm_hw_params(handle, params);
if (rc < 0) {
fprintf(stderr,
"unable to set hw parameters: %s\n",
snd_strerror(rc));
exit(1);
}
/* Use a buffer large enough to hold one period */
snd_pcm_hw_params_get_period_size(params, &frames,
&dir);
size = frames * 4; /* 2 bytes/sample, 2 channels */
buffer = (char *) malloc(size);
/* We want to loop for 5 seconds */
snd_pcm_hw_params_get_period_time(params,
&val, &dir);
/* 5 seconds in microseconds divided by
* period time */
loops = 5000000 / val;
while (1) {
// loops--;
// printf("%ld\n", loops);
rc = read(0, buffer, size);
/**/
if (rc == 0) {
fprintf(stderr, "end of file on input\n");
break;
} else if (rc != size) {
fprintf(stderr,
"short read: read %d bytes\n", rc);
}
rc = snd_pcm_writei(handle, buffer, frames);
if (rc == -EPIPE) {
/* EPIPE means underrun */
fprintf(stderr, "underrun occurred\n");
snd_pcm_prepare(handle);
} else if (rc < 0) {
fprintf(stderr,
"error from writei: %s\n",
snd_strerror(rc));
} else if (rc != (int)frames) {
fprintf(stderr,
"short write, write %d frames\n", rc);
}
/**/
}
snd_pcm_drain(handle);
snd_pcm_close(handle);
free(buffer);
return 0;
}
To play the music in the background, we add the subprocess function to call the music playback while the main function is still running to check the distance data from sensor in order to switch the music. when the distance reach the given range, the main function would create the subprocess to initial the music play thread.
class Popen
{
public:
friend struct detail::ArgumentDeducer;
friend class detail::Child;
template <typename... Args>
Popen(const std::string& cmd_args, Args&& ...args):
args_(cmd_args)
{
vargs_ = util::split(cmd_args);
init_args(std::forward<Args>(args)...);
// Setup the communication channels of the Popen class
stream_.setup_comm_channels();
if (!defer_process_start_) execute_process();
}
template <typename... Args>
Popen(std::initializer_list<const char*> cmd_args, Args&& ...args)
{
vargs_.insert(vargs_.end(), cmd_args.begin(), cmd_args.end());
init_args(std::forward<Args>(args)...);
// Setup the communication channels of the Popen class
stream_.setup_comm_channels();
if (!defer_process_start_) execute_process();
}
void start_process() noexcept(false);
int pid() const noexcept { return child_pid_; }
int retcode() const noexcept { return retcode_; }
int wait() noexcept(false);
int poll() noexcept(false);
// Does not fail, Caller is expected to recheck the
// status with a call to poll()
void kill(int sig_num = 9);
void set_out_buf_cap(size_t cap) { stream_.set_out_buf_cap(cap); }
void set_err_buf_cap(size_t cap) { stream_.set_err_buf_cap(cap); }
int send(const char* msg, size_t length)
{ return stream_.send(msg, length); }
int send(const std::vector<char>& msg)
{ return stream_.send(msg); }
std::pair<OutBuffer, ErrBuffer> communicate(const char* msg, size_t length)
{
auto res = stream_.communicate(msg, length);
retcode_ = wait();
return res;
}
std::pair<OutBuffer, ErrBuffer> communicate(const std::vector<char>& msg)
{
auto res = stream_.communicate(msg);
retcode_ = wait();
return res;
}
std::pair<OutBuffer, ErrBuffer> communicate()
{
return communicate(nullptr, 0);
}
FILE* input() { return stream_.input(); }
FILE* output() { return stream_.output();}
FILE* error() { return stream_.error(); }
/// Stream close APIs
void close_input() { stream_.input_.reset(); }
void close_output() { stream_.output_.reset(); }
void close_error() { stream_.error_.reset(); }
private:
template <typename F, typename... Args>
void init_args(F&& farg, Args&&... args);
void init_args();
void populate_c_argv();
void execute_process() noexcept(false);
private:
detail::Streams stream_;
bool defer_process_start_ = false;
bool close_fds_ = false;
bool has_preexec_fn_ = false;
bool shell_ = false;
bool session_leader_ = false;
std::string exe_name_;
std::string cwd_;
std::map<std::string, std::string> env_;
preexec_func preexec_fn_;
// Command in string format
std::string args_;
// Comamnd provided as sequence
std::vector<std::string> vargs_;
std::vector<char*> cargv_;
bool child_created_ = false;
// Pid of the child process
int child_pid_ = -1;
int retcode_ = -1;
};
inline void Popen::init_args() {
populate_c_argv();
}
template <typename F, typename... Args>
inline void Popen::init_args(F&& farg, Args&&... args)
{
detail::ArgumentDeducer argd(this);
argd.set_option(std::forward<F>(farg));
init_args(std::forward<Args>(args)...);
}
inline void Popen::populate_c_argv()
{
cargv_.clear();
cargv_.reserve(vargs_.size() + 1);
for (auto& arg : vargs_) cargv_.push_back(&arg[0]);
cargv_.push_back(nullptr);
}
We come across the problem when the main program running, the switching music functions would get into dead state after being called some times. In the first, we thought the problem could in the music playback function or in creating too many subprocess without killing them when the function jump out. After we test the main function, we find the problem actually is in the communication between parent process and subprocess. So we fix it by adding poll function which would check whether the subprocess is running or not and stop sending signal to subprocess when it actually being killed.
Create an account to leave a comment. Already have an account? Log In.
Become a member to follow this project and never miss any updates