|
|
|
|
@ -1,71 +1,106 @@ |
|
|
|
|
// input: ALSA
|
|
|
|
|
void* input_alsa(void* data) |
|
|
|
|
{ |
|
|
|
|
struct audio_data *audio = (struct audio_data *)data; |
|
|
|
|
signed char *buffer; |
|
|
|
|
snd_pcm_t *handle; |
|
|
|
|
snd_pcm_hw_params_t *params; |
|
|
|
|
unsigned int val; |
|
|
|
|
snd_pcm_uframes_t frames; |
|
|
|
|
val = 44100; |
|
|
|
|
int i, n, o, size, dir, err, lo; |
|
|
|
|
int tempr, templ; |
|
|
|
|
int radj, ladj; |
|
|
|
|
|
|
|
|
|
// assuming stereo
|
|
|
|
|
#define CHANNELS_COUNT 2 |
|
|
|
|
#define SAMPLE_RATE 44100 |
|
|
|
|
|
|
|
|
|
void initialize_audio_parameters(snd_pcm_t** handle, struct audio_data* audio, |
|
|
|
|
snd_pcm_uframes_t* frames) { |
|
|
|
|
// alsa: open device to capture audio
|
|
|
|
|
if ((err = snd_pcm_open(&handle, audio-> source, SND_PCM_STREAM_CAPTURE, 0) < 0)) { |
|
|
|
|
fprintf(stderr, |
|
|
|
|
"error opening stream: %s\n", |
|
|
|
|
snd_strerror(err)); |
|
|
|
|
int err = snd_pcm_open(handle, audio->source, SND_PCM_STREAM_CAPTURE, 0); |
|
|
|
|
if (err < 0) { |
|
|
|
|
fprintf(stderr, "error opening stream: %s\n", snd_strerror(err)); |
|
|
|
|
exit(EXIT_FAILURE); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#ifdef DEBUG |
|
|
|
|
else printf("open stream successful\n"); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
snd_pcm_hw_params_alloca(¶ms); //assembling params
|
|
|
|
|
snd_pcm_hw_params_any (handle, params); //setting defaults or something
|
|
|
|
|
snd_pcm_hw_params_set_access(handle, params, |
|
|
|
|
SND_PCM_ACCESS_RW_INTERLEAVED); //interleaved mode right left right left
|
|
|
|
|
snd_pcm_hw_params_set_format(handle, params, |
|
|
|
|
SND_PCM_FORMAT_S16_LE); //trying to set 16bit
|
|
|
|
|
snd_pcm_hw_params_set_channels(handle, params, 2); //assuming stereo
|
|
|
|
|
val = 44100; |
|
|
|
|
snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); //trying 44100 rate
|
|
|
|
|
frames = 256; |
|
|
|
|
snd_pcm_hw_params_set_period_size_near(handle, params, &frames, |
|
|
|
|
&dir); //number of frames pr read
|
|
|
|
|
|
|
|
|
|
err = snd_pcm_hw_params(handle, params); //attempting to set params
|
|
|
|
|
snd_pcm_hw_params_t* params; |
|
|
|
|
snd_pcm_hw_params_alloca(¶ms); // assembling params
|
|
|
|
|
snd_pcm_hw_params_any(*handle, params); // setting defaults or something
|
|
|
|
|
// interleaved mode right left right left
|
|
|
|
|
snd_pcm_hw_params_set_access(*handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); |
|
|
|
|
// trying to set 16bit
|
|
|
|
|
snd_pcm_hw_params_set_format(*handle, params, SND_PCM_FORMAT_S16_LE); |
|
|
|
|
snd_pcm_hw_params_set_channels(*handle, params, CHANNELS_COUNT); |
|
|
|
|
unsigned int sample_rate = SAMPLE_RATE; |
|
|
|
|
// trying our rate
|
|
|
|
|
snd_pcm_hw_params_set_rate_near(*handle, params, &sample_rate, NULL); |
|
|
|
|
// number of frames pr read
|
|
|
|
|
snd_pcm_hw_params_set_period_size_near(*handle, params, frames, NULL); |
|
|
|
|
err = snd_pcm_hw_params(*handle, params); // attempting to set params
|
|
|
|
|
if (err < 0) { |
|
|
|
|
fprintf(stderr, |
|
|
|
|
"unable to set hw parameters: %s\n", |
|
|
|
|
snd_strerror(err)); |
|
|
|
|
fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(err)); |
|
|
|
|
exit(EXIT_FAILURE); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
snd_pcm_hw_params_get_format(params, |
|
|
|
|
(snd_pcm_format_t * )&val); //getting actual format
|
|
|
|
|
//converting result to number of bits
|
|
|
|
|
if (val < 6)audio->format = 16; |
|
|
|
|
else if (val > 5 && val < 10)audio->format = 24; |
|
|
|
|
else if (val > 9)audio->format = 32; |
|
|
|
|
// getting actual format
|
|
|
|
|
snd_pcm_hw_params_get_format(params, (snd_pcm_format_t*)&sample_rate); |
|
|
|
|
// converting result to number of bits
|
|
|
|
|
if (sample_rate <= 5) |
|
|
|
|
audio->format = 16; |
|
|
|
|
else if (sample_rate <= 9 ) |
|
|
|
|
audio->format = 24; |
|
|
|
|
else |
|
|
|
|
audio->format = 32; |
|
|
|
|
snd_pcm_hw_params_get_rate(params, &audio->rate, NULL); |
|
|
|
|
snd_pcm_hw_params_get_period_size(params, frames, NULL); |
|
|
|
|
// snd_pcm_hw_params_get_period_time(params, &sample_rate, &dir);
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
snd_pcm_hw_params_get_rate(params, &audio->rate, &dir); //getting rate
|
|
|
|
|
int get_certain_frame(signed char* buffer, int buffer_index, int adjustment) { |
|
|
|
|
// using the 10 upper bits this would give me a vert res of 1024, enough...
|
|
|
|
|
int temp = buffer[buffer_index + adjustment - 1] << 2; |
|
|
|
|
int lo = buffer[buffer_index + adjustment - 2] >> 6; |
|
|
|
|
if (lo < 0) |
|
|
|
|
lo = abs(lo) + 1; |
|
|
|
|
if (temp >= 0) |
|
|
|
|
temp += lo; |
|
|
|
|
else |
|
|
|
|
temp -= lo; |
|
|
|
|
return temp; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
snd_pcm_hw_params_get_period_size(params, &frames, &dir); |
|
|
|
|
snd_pcm_hw_params_get_period_time(params, &val, &dir); |
|
|
|
|
void fill_audio_outs(struct audio_data* audio, signed char* buffer, |
|
|
|
|
const int size) { |
|
|
|
|
int radj = audio->format / 4; // adjustments for interleaved
|
|
|
|
|
int ladj = audio->format / 8; |
|
|
|
|
static int audio_out_buffer_index = 0; |
|
|
|
|
// sorting out one channel and only biggest octet
|
|
|
|
|
for (int buffer_index = 0; buffer_index < size; buffer_index += ladj * 2) { |
|
|
|
|
// first channel
|
|
|
|
|
int tempr = get_certain_frame(buffer, buffer_index, radj); |
|
|
|
|
// second channel
|
|
|
|
|
int templ = get_certain_frame(buffer, buffer_index, ladj); |
|
|
|
|
|
|
|
|
|
// mono: adding channels and storing it in the buffer
|
|
|
|
|
if (audio->channels == 1) |
|
|
|
|
audio->audio_out_l[audio_out_buffer_index] = (templ + tempr) / 2; |
|
|
|
|
else { // stereo storing channels in buffer
|
|
|
|
|
audio->audio_out_l[audio_out_buffer_index] = templ; |
|
|
|
|
audio->audio_out_r[audio_out_buffer_index] = tempr; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
size = frames * (audio->format / 8) * 2; // frames * bits/8 * 2 channels
|
|
|
|
|
buffer = malloc(size); |
|
|
|
|
radj = audio->format / 4; //adjustments for interleaved
|
|
|
|
|
ladj = audio->format / 8; |
|
|
|
|
o = 0; |
|
|
|
|
while (1) { |
|
|
|
|
if (++audio_out_buffer_index == 2048 - 1) |
|
|
|
|
audio_out_buffer_index = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#define FRAMES_NUMBER 256 |
|
|
|
|
|
|
|
|
|
void* input_alsa(void* data) { |
|
|
|
|
struct audio_data* audio = (struct audio_data*)data; |
|
|
|
|
snd_pcm_t* handle; |
|
|
|
|
snd_pcm_uframes_t frames = FRAMES_NUMBER; |
|
|
|
|
|
|
|
|
|
initialize_audio_parameters(&handle, audio, &frames); |
|
|
|
|
|
|
|
|
|
err = snd_pcm_readi(handle, buffer, frames); |
|
|
|
|
// frames * bits/8 * channels
|
|
|
|
|
const int size = frames * (audio->format / 8) * CHANNELS_COUNT; |
|
|
|
|
signed char* buffer = malloc(size); |
|
|
|
|
while (1) { |
|
|
|
|
int err = snd_pcm_readi(handle, buffer, frames); |
|
|
|
|
if (err == -EPIPE) { |
|
|
|
|
/* EPIPE means overrun */ |
|
|
|
|
#ifdef DEBUG |
|
|
|
|
@ -81,53 +116,11 @@ void* input_alsa(void* data) |
|
|
|
|
fprintf(stderr, "short read, read %d %d frames\n", err, (int)frames); |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//sorting out one channel and only biggest octet
|
|
|
|
|
n = 0; //frame counter
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < size ; i = i + (ladj) * 2) { |
|
|
|
|
|
|
|
|
|
//first channel
|
|
|
|
|
tempr = ((buffer[i + (radj) - 1 ] << |
|
|
|
|
2)); //using the 10 upper bits this would give me a vert res of 1024, enough...
|
|
|
|
|
|
|
|
|
|
lo = ((buffer[i + (radj) - 2] >> 6)); |
|
|
|
|
if (lo < 0)lo = abs(lo) + 1; |
|
|
|
|
if (tempr >= 0)tempr = tempr + lo; |
|
|
|
|
if (tempr < 0)tempr = tempr - lo; |
|
|
|
|
|
|
|
|
|
//other channel
|
|
|
|
|
templ = (buffer[i + (ladj) - 1] << 2); |
|
|
|
|
lo = (buffer[i + (ladj) - 2] >> 6); |
|
|
|
|
if (lo < 0)lo = abs(lo) + 1; |
|
|
|
|
if (templ >= 0)templ = templ + lo; |
|
|
|
|
else templ = templ - lo; |
|
|
|
|
|
|
|
|
|
//mono: adding channels and storing it in the buffer
|
|
|
|
|
if (audio->channels == 1) audio->audio_out_l[o] = (tempr + templ) / 2; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//stereo storing channels in buffer
|
|
|
|
|
if (audio->channels == 2) { |
|
|
|
|
audio->audio_out_l[o] = templ; |
|
|
|
|
audio->audio_out_r[o] = tempr; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
o++; |
|
|
|
|
if (o == 2048 - 1)o = 0; |
|
|
|
|
|
|
|
|
|
n++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fill_audio_outs(audio, buffer, size); |
|
|
|
|
if (audio->terminate == 1) { |
|
|
|
|
free(buffer); |
|
|
|
|
snd_pcm_close(handle); |
|
|
|
|
break; |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|