portaudio support

master
Nikola Pavlica 7 years ago
parent 80c4064fb1
commit 24c872936f
  1. 12
      cava.c
  2. 18
      config.c
  3. 13
      configure.ac
  4. 3
      example_files/config
  5. 196
      input/portaudio.c
  6. 1
      input/portaudio.h

@ -54,6 +54,11 @@
#include "input/alsa.c" #include "input/alsa.c"
#endif #endif
#ifdef PORTAUDIO
#include "input/portaudio.c"
#include "input/portaudio.h"
#endif
#ifdef PULSE #ifdef PULSE
#include "input/pulse.h" #include "input/pulse.h"
#include "input/pulse.c" #include "input/pulse.c"
@ -471,6 +476,13 @@ as of 0.4.0 all options are specified in config file, see in '/home/username/.co
} }
#endif #endif
#ifdef PORTAUDIO
if (p.im == 6) {
thr_id = pthread_create(&p_thread, NULL, input_portaudio, (void*)&audio);
audio.rate = 44100;
}
#endif
if (p.highcf > audio.rate / 2) { if (p.highcf > audio.rate / 2) {
cleanup(); cleanup();
fprintf(stderr, fprintf(stderr,

@ -167,6 +167,13 @@ if (strcmp(inputMethod, "shmem") == 0) {
return false; return false;
#endif #endif
} }
if (strcmp(inputMethod, "portaudio") == 0) {
p->im = 6;
#ifndef PORTAUDIO
write_errorf(error, "cava was built without portaudio support\n");
return false;
#endif
}
if (p->im == 0) { if (p->im == 0) {
write_errorf(error, "input method '%s' is not supported, supported methods are: %s\n", write_errorf(error, "input method '%s' is not supported, supported methods are: %s\n",
inputMethod, supportedInput); inputMethod, supportedInput);
@ -412,6 +419,11 @@ if (colorsOnly) {
//setting fifo to defaualt if no other input modes supported //setting fifo to defaualt if no other input modes supported
inputMethod = (char *)iniparser_getstring(ini, "input:method", "fifo"); inputMethod = (char *)iniparser_getstring(ini, "input:method", "fifo");
//setting portaudio to default if supported
#ifdef ALSA
inputMethod = (char *)iniparser_getstring(ini, "input:method", "portaudio");
#endif
//setting alsa to defaualt if supported //setting alsa to defaualt if supported
#ifdef ALSA #ifdef ALSA
inputMethod = (char *)iniparser_getstring(ini, "input:method", "alsa"); inputMethod = (char *)iniparser_getstring(ini, "input:method", "alsa");
@ -506,6 +518,12 @@ if (strcmp(inputMethod, "shmem") == 0) {
p->audio_source = (char *)iniparser_getstring(ini, "input:source", "/squeezelite-00:00:00:00:00:00"); p->audio_source = (char *)iniparser_getstring(ini, "input:source", "/squeezelite-00:00:00:00:00:00");
} }
#endif #endif
#ifdef PORTAUDIO
if (strcmp(inputMethod, "portaudio") == 0) {
p->im = 6;
p->audio_source = (char *)iniparser_getstring(ini, "input:source", "auto");
}
#endif
return validate_config(supportedInput, params, error); return validate_config(supportedInput, params, error);
//iniparser_freedict(ini); //iniparser_freedict(ini);

@ -69,6 +69,19 @@ AC_CHECK_LIB(pulse-simple, pa_simple_new, have_pulse=yes, have_pulse=no)
AC_MSG_NOTICE([WARNING: No pusleaudio dev files found building without pulseaudio support]) AC_MSG_NOTICE([WARNING: No pusleaudio dev files found building without pulseaudio support])
fi fi
dnl ######################
dnl checking for portaudio dev
dnl ######################
AC_CHECK_LIB(portaudio, Pa_Initialize, have_portaudio=yes, have_portaudio=no)
if [[ $have_portaudio = "yes" ]] ; then
LIBS="$LIBS -lportaudio"
CPPFLAGS="$CPPFLAGS -DPORTAUDIO"
fi
if [[ $have_portaudio = "no" ]] ; then
AC_MSG_NOTICE([WARNING: No portaudio dev files found building without portaudio support])
fi
dnl ###################### dnl ######################
dnl checking for sndio dev dnl checking for sndio dev
dnl ###################### dnl ######################

@ -68,6 +68,9 @@
; method = shmem ; method = shmem
; source = /squeezelite-AA:BB:CC:DD:EE:FF ; source = /squeezelite-AA:BB:CC:DD:EE:FF
; method = portaudio
; source = auto
[output] [output]

@ -0,0 +1,196 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <portaudio.h>
#include "portaudio.h"
#include "fifo.h"
#define BUFFERSIZE 4096
#define SAMPLE_SILENCE 32768
#define PA_SAMPLE_TYPE paInt16
typedef short SAMPLE;
typedef struct {
int frameIndex; /* Index into sample array. */
int maxFrameIndex;
SAMPLE *recordedSamples;
} paTestData;
static struct audio_data *audio;
static int n = 0;
static int recordCallback(const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags, void *userData) {
paTestData *data = (paTestData*)userData;
const SAMPLE *rptr = (const SAMPLE*)inputBuffer;
long framesToCalc;
long i;
int finished;
unsigned long framesLeft = data->maxFrameIndex - data->frameIndex;
(void) outputBuffer; // Prevent unused variable warnings.
(void) timeInfo;
(void) statusFlags;
(void) userData;
if( framesLeft < framesPerBuffer ) {
framesToCalc = framesLeft;
finished = paComplete;
} else {
framesToCalc = framesPerBuffer;
finished = paContinue;
}
if(inputBuffer == NULL) {
for(i=0; i<framesToCalc; i++) {
if(audio->channels == 1) audio->audio_out_l[n] = SAMPLE_SILENCE;
if(audio->channels == 2) {
audio->audio_out_l[n] = SAMPLE_SILENCE;
audio->audio_out_r[n] = SAMPLE_SILENCE;
}
if(n == BUFSIZE-1) n = 0;
}
} else {
for(i=0; i<framesToCalc; i++) {
if(audio->channels == 1) {
audio->audio_out_l[n] = (rptr[0] + rptr[1]) / 2;
rptr += 2;
}
if(audio->channels == 2) {
audio->audio_out_l[n] = *rptr++;
audio->audio_out_r[n] = *rptr++;
}
n++;
if(n == BUFSIZE-1) n = 0;
}
}
data->frameIndex += framesToCalc;
if(finished == paComplete) {
data->frameIndex = 0;
finished = paContinue;
}
return finished;
}
void portaudio_simple_free(paTestData data) {
Pa_Terminate();
free(data.recordedSamples);
}
void* input_portaudio(void *audiodata) {
audio = (struct audio_data *)audiodata;
PaStreamParameters inputParameters;
PaStream* stream;
PaError err = paNoError;
paTestData data;
// start portaudio
err = Pa_Initialize();
if(err != paNoError) {
fprintf(stderr, "Error: unable to initilize portaudio - %s\n", Pa_GetErrorText(err));
exit(EXIT_FAILURE);
}
// get portaudio device
int deviceNum = -1, numOfDevices = Pa_GetDeviceCount();
if(!strcmp(audio->source, "list")) {
if(numOfDevices < 0) {
fprintf(stderr, "Error: portaudio was unable to find a audio device! Code: 0x%x\n", numOfDevices);
exit(EXIT_FAILURE);
}
for(int i = 0; i < numOfDevices; i++) {
const PaDeviceInfo *deviceInfo = Pa_GetDeviceInfo(i);
printf("Device #%d: %s\n"
"\tInput Channels: %d\n"
"\tOutput Channels: %d\n"
"\tDefault SampleRate: %lf\n",
i+1, deviceInfo->name, deviceInfo->maxInputChannels,
deviceInfo->maxOutputChannels, deviceInfo->defaultSampleRate);
}
exit(EXIT_SUCCESS);
} else if(!strcmp(audio->source, "auto")) {
deviceNum = Pa_GetDefaultInputDevice();
if(deviceNum == paNoDevice) {
fprintf(stderr, "Error: no portaudio input device found\n");
exit(EXIT_FAILURE);
}
} else if(sscanf(audio->source,"%d", &deviceNum)) {
if(deviceNum > numOfDevices) {
fprintf(stderr, "Error: Invalid input device!\n");
exit(EXIT_FAILURE);
}
deviceNum--;
} else {
for(int i = 0; i < numOfDevices; i++) {
const PaDeviceInfo *deviceInfo = Pa_GetDeviceInfo(i);
if(!strcmp(audio->source, deviceInfo->name)) {
deviceNum=i;
break;
}
}
if(deviceNum==-1) {
fprintf(stderr, "Error: No such device '%s'!\n", audio->source);
exit(EXIT_FAILURE);
}
}
inputParameters.device = deviceNum;
// set parameters
data.maxFrameIndex = BUFSIZE;
data.recordedSamples = (SAMPLE *)malloc(2*BUFSIZE*sizeof(SAMPLE));
if(data.recordedSamples == NULL) {
fprintf(stderr, "Error: failure in memory allocation!\n");
exit(EXIT_FAILURE);
} else memset(data.recordedSamples, 0x00, 2*BUFSIZE);
inputParameters.channelCount = 2;
inputParameters.sampleFormat = PA_SAMPLE_TYPE;
inputParameters.suggestedLatency = Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency;
inputParameters.hostApiSpecificStreamInfo = NULL;
// set it to work
err = Pa_OpenStream(&stream, &inputParameters, NULL, audio->rate, BUFSIZE,
paClipOff, recordCallback, &data);
if(err != paNoError) {
fprintf(stderr, "Error: failure in opening stream (%x)\n", err);
exit(EXIT_FAILURE);
}
// main loop
while(1){
// start recording
data.frameIndex = 0;
err = Pa_StartStream(stream);
if(err != paNoError) {
fprintf(stderr, "Error: failure in starting stream (%x)\n", err);
exit(EXIT_FAILURE);
}
// record
while((err = Pa_IsStreamActive(stream)) == 1) {
Pa_Sleep(5);
if(audio->terminate == 1) break;
}
// check for errors
if(err < 0) {
fprintf(stderr, "Error: failure in recording audio (%x)\n", err);
exit(EXIT_FAILURE);
}
// check if it bailed
if(audio->terminate == 1) break;
}
// close stream
if((err = Pa_CloseStream(stream)) != paNoError) {
fprintf(stderr, "Error: failure in closing stream (%x)\n", err);
exit(EXIT_FAILURE);
}
portaudio_simple_free(data);
return 0;
}

@ -0,0 +1 @@
void* input_portaudio(void *audiodata);
Loading…
Cancel
Save