diff --git a/src/audio.c b/src/audio.c index 1e5e763..535081d 100644 --- a/src/audio.c +++ b/src/audio.c @@ -4,25 +4,7 @@ #include #include -int audio_default_callback(const void *input, void *output, - unsigned long frameCount, const PaStreamCallbackTimeInfo *timeInfo, - PaStreamCallbackFlags statusFlags, void *userData) { - (void)timeInfo; - (void)statusFlags; - - audio_t *aud = (audio_t *)userData; - - int encLen = opus_encode_float(aud->opusEnc, (float *)input, frameCount, aud->opusBuf, aud->opusBufSz); - (void)encLen; - int frameSize = opus_decode_float(aud->opusDec, aud->opusBuf, aud->opusBufSz, (float *)output, frameCount, 0); - (void)frameSize; - - // printf("%i %i | %li %li\n", encLen, frameSize, frameCount, aud->opusBufSz); - - return paContinue; -} - -int audio_init_default(audio_t *aud, int channels, int sampleRate, int frameSize, PaStreamCallback callback) { +int audio_init(audio_t *aud, int channels, int sampleRate, int frameSize) { PaError paErr; int opusErr; @@ -31,9 +13,6 @@ int audio_init_default(audio_t *aud, int channels, int sampleRate, int frameSize return -1; } - aud->opusBufSz = frameSize * channels; - aud->opusBuf = (uint8_t *)malloc(aud->opusBufSz * sizeof(uint8_t)); - aud->opusEnc = opus_encoder_create(sampleRate, channels, OPUS_APPLICATION_VOIP, &opusErr); if (opusErr != OPUS_OK) { fprintf(stderr, "An Opus encoder cannot be created: %s\n", opus_strerror(opusErr)); @@ -46,12 +25,15 @@ int audio_init_default(audio_t *aud, int channels, int sampleRate, int frameSize return -1; } - if ((paErr = Pa_OpenDefaultStream(&aud->stream, channels, channels, paFloat32, - sampleRate, frameSize, callback, aud)) != paNoError) { + if ((paErr = Pa_OpenDefaultStream(&aud->stream, channels, channels, AUDIO_SAMPLE_FORMAT, + sampleRate, frameSize, NULL, NULL)) != paNoError) { fprintf(stderr, "Cannot open a PortAudio stream: %s\n", Pa_GetErrorText(paErr)); return -1; } + aud->bufferSz = frameSize * channels; + aud->buffer = (audio_sample_t *)malloc(aud->bufferSz * sizeof(audio_sample_t)); + if ((paErr = Pa_StartStream(aud->stream)) != paNoError) { fprintf(stderr, "Cannot start a PortAudio stream: %s\n", Pa_GetErrorText(paErr)); return -1; @@ -79,15 +61,56 @@ int audio_destroy(audio_t *aud) { fprintf(stderr, "Cannot terminate PortAudio: %s\n", Pa_GetErrorText(paErr)); return -1; } - + + if (aud->buffer) + free(aud->buffer); + if (aud->opusEnc) opus_encoder_destroy(aud->opusEnc); if (aud->opusDec) opus_decoder_destroy(aud->opusDec); - if (aud->opusBuf) - free(aud->opusBuf); + return 0; +} + +/* +int encLen = opus_encode_float(aud->opusEnc, (float *)input, frameCount, aud->opusBuf, aud->opusBufSz); + (void)encLen; + int frameSize = opus_decode_float(aud->opusDec, aud->opusBuf, aud->opusBufSz, (float *)output, frameCount, 0); + (void)frameSize; +*/ + +int audio_read(audio_t *aud, uint8_t *outputData, size_t outputLen) { + PaError paErr; + + if ((paErr = Pa_ReadStream(aud->stream, aud->buffer, aud->bufferSz)) != paNoError) { + fprintf(stderr, "Cannot read from a PortAudio stream: %s\n", Pa_GetErrorText(paErr)); + return -1; + } + + int encodedLen = opus_encode_float(aud->opusEnc, aud->buffer, aud->bufferSz, outputData, outputLen); + if (encodedLen < 0) { + fprintf(stderr, "Opus failed to encode: %s\n", opus_strerror(encodedLen)); + return -1; + } + + return 0; +} + +int audio_write(audio_t *aud, const uint8_t *inputData, size_t inputLen) { + PaError paErr; + + int frameSize = opus_decode_float(aud->opusDec, inputData, inputLen, aud->buffer, aud->bufferSz, 0); + if (frameSize < 0) { + fprintf(stderr, "Opus failed to decode: %s\n", opus_strerror(frameSize)); + return -1; + } + + if ((paErr = Pa_WriteStream(aud->stream, aud->buffer, aud->bufferSz)) != paNoError) { + fprintf(stderr, "Cannot write to a PortAudio stream: %s\n", Pa_GetErrorText(paErr)); + return -1; + } return 0; } \ No newline at end of file diff --git a/src/audio.h b/src/audio.h index ee0f19c..4d12482 100644 --- a/src/audio.h +++ b/src/audio.h @@ -7,19 +7,22 @@ #include #include +#define AUDIO_SAMPLE_FORMAT paFloat32 +typedef float audio_sample_t; + typedef struct audio_t { - PaStream *stream; + PaStream *stream; OpusEncoder *opusEnc; OpusDecoder *opusDec; - uint8_t *opusBuf; - size_t opusBufSz; + + audio_sample_t *buffer; + size_t bufferSz; } audio_t; -int audio_default_callback(const void *input, void *output, - unsigned long frameCount, const PaStreamCallbackTimeInfo *timeInfo, - PaStreamCallbackFlags statusFlags, void *userData); - -int audio_init_default(audio_t *aud, int channels, int sampleRate, int frameSize, PaStreamCallback *callback); +int audio_init(audio_t *aud, int channels, int sampleRate, int frameSize); int audio_destroy(audio_t *aud); +int audio_read(audio_t *aud, uint8_t *outputData, size_t outputLen); +int audio_write(audio_t *aud, const uint8_t *inputData, size_t inputLen); + #endif /* _AUDIO_H_ */ \ No newline at end of file