#include "rpi_microphone.h" #include #include #define CHANNELS_COUNT 1 #define SAMPLE_RATE 44100 snd_pcm_t *capture_handle; int write_to_fftw_input_buffers(int16_t frames, int16_t buf[frames * 2], audio_data_t *audio); void *microphone_listen(void *arg) { audio_data_t *audio = (audio_data_t *)arg; microphone_setup(audio); while (1) { microphone_exec(audio); } } void microphone_setup(audio_data_t *audio) { int err; snd_pcm_hw_params_t *hw_params; snd_pcm_uframes_t frames = audio->FFTtreblebufferSize; unsigned int sampleRate = SAMPLE_RATE; if ((err = snd_pcm_open(&capture_handle, audio->source, SND_PCM_STREAM_CAPTURE, 0)) < 0) { fprintf(stderr, "cannot open audio device %s (%s)\n", audio->source, snd_strerror(err)); exit(1); } if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) { fprintf(stderr, "cannot allocate hardware parameter structure (%s)\n", snd_strerror(err)); exit(1); } if ((err = snd_pcm_hw_params_any(capture_handle, hw_params)) < 0) { fprintf(stderr, "cannot initialize hardware parameter structure (%s)\n", snd_strerror(err)); exit(1); } if ((err = snd_pcm_hw_params_set_access(capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { fprintf(stderr, "cannot set access type (%s)\n", snd_strerror(err)); exit(1); } if ((err = snd_pcm_hw_params_set_format(capture_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) { fprintf(stderr, "cannot set sample format (%s)\n", snd_strerror(err)); exit(1); } if ((err = snd_pcm_hw_params_set_channels(capture_handle, hw_params, CHANNELS_COUNT)) < 0) { fprintf(stderr, "cannot set channel count (%s)\n", snd_strerror(err)); exit(1); } if ((err = snd_pcm_hw_params_set_rate_near(capture_handle, hw_params, &sampleRate, NULL)) < 0) { fprintf(stderr, "cannot set sample rate (%s)\n", snd_strerror(err)); exit(1); } if ((err = snd_pcm_hw_params_set_period_size_near(capture_handle, hw_params, &frames, NULL)) < 0) { fprintf(stderr, "cannot set period size (%s)\n", snd_strerror(err)); exit(1); } if ((err = snd_pcm_hw_params(capture_handle, hw_params)) < 0) { fprintf(stderr, "cannot set parameters (%s)\n", snd_strerror(err)); exit(1); } snd_pcm_hw_params_get_rate(hw_params, &audio->rate, NULL); snd_pcm_hw_params_free(hw_params); if ((err = snd_pcm_prepare(capture_handle)) < 0) { fprintf(stderr, "cannot prepare audio interface for use (%s)\n", snd_strerror(err)); exit(1); } } void microphone_exec(audio_data_t *audio) { int err; snd_pcm_uframes_t buffer_size; snd_pcm_uframes_t period_size; snd_pcm_uframes_t frames = audio->FFTtreblebufferSize; snd_pcm_get_params(capture_handle, &buffer_size, &period_size); int16_t buf[period_size]; frames = period_size / 2; err = snd_pcm_readi(capture_handle, buf, frames); if (err == -EPIPE) { /* EPIPE means overrun */ fprintf(stderr, "overrun occurred\n"); snd_pcm_prepare(capture_handle); } else if (err < 0) { fprintf(stderr, "error from read: %s\n", snd_strerror(err)); } else if (err != (int)frames) { fprintf(stderr, "short read, read %d %d frames\n", err, (int)frames); } pthread_mutex_lock(&audio->lock); write_to_fftw_input_buffers(frames, buf, audio); pthread_mutex_unlock(&audio->lock); } void reset_output_buffers(audio_data_t *data) { memset(data->in_bass_l, 0, sizeof(double) * data->FFTbassbufferSize); memset(data->in_mid_l, 0, sizeof(double) * data->FFTmidbufferSize); memset(data->in_treble_l, 0, sizeof(double) * data->FFTtreblebufferSize); memset(data->in_bass_l_raw, 0, sizeof(double) * data->FFTbassbufferSize); memset(data->in_mid_l_raw, 0, sizeof(double) * data->FFTmidbufferSize); memset(data->in_treble_l_raw, 0, sizeof(double) * data->FFTtreblebufferSize); } int write_to_fftw_input_buffers(int16_t frames, int16_t buf[frames * 2], audio_data_t *audio) { if (frames == 0) return 0; for (uint16_t n = audio->FFTbassbufferSize; n > frames; n = n - frames) { for (uint16_t i = 1; i <= frames; i++) { audio->in_bass_l_raw[n - i] = audio->in_bass_l_raw[n - i - frames]; } } for (uint16_t n = audio->FFTmidbufferSize; n > frames; n = n - frames) { for (uint16_t i = 1; i <= frames; i++) { audio->in_mid_l_raw[n - i] = audio->in_mid_l_raw[n - i - frames]; } } for (uint16_t n = audio->FFTtreblebufferSize; n > frames; n = n - frames) { for (uint16_t i = 1; i <= frames; i++) { audio->in_treble_l_raw[n - i] = audio->in_treble_l_raw[n - i - frames]; } } uint16_t n = frames - 1; for (uint16_t i = 0; i < frames; i++) { audio->in_bass_l_raw[n] = buf[i * 2]; audio->in_mid_l_raw[n] = audio->in_bass_l_raw[n]; audio->in_treble_l_raw[n] = audio->in_bass_l_raw[n]; n--; } // Hann Window for (int i = 0; i < audio->FFTbassbufferSize; i++) { audio->in_bass_l[i] = audio->bass_multiplier[i] * audio->in_bass_l_raw[i]; } for (int i = 0; i < audio->FFTmidbufferSize; i++) { audio->in_mid_l[i] = audio->mid_multiplier[i] * audio->in_mid_l_raw[i]; } for (int i = 0; i < audio->FFTtreblebufferSize; i++) { audio->in_treble_l[i] = audio->treble_multiplier[i] * audio->in_treble_l_raw[i]; } return 0; }