Completed an audio module using a blocking I/O.
This commit is contained in:
parent
64176055d0
commit
f13e7e20fd
75
src/audio.c
75
src/audio.c
@ -4,25 +4,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
int audio_default_callback(const void *input, void *output,
|
int audio_init(audio_t *aud, int channels, int sampleRate, int frameSize) {
|
||||||
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) {
|
|
||||||
PaError paErr;
|
PaError paErr;
|
||||||
int opusErr;
|
int opusErr;
|
||||||
|
|
||||||
@ -31,9 +13,6 @@ int audio_init_default(audio_t *aud, int channels, int sampleRate, int frameSize
|
|||||||
return -1;
|
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);
|
aud->opusEnc = opus_encoder_create(sampleRate, channels, OPUS_APPLICATION_VOIP, &opusErr);
|
||||||
if (opusErr != OPUS_OK) {
|
if (opusErr != OPUS_OK) {
|
||||||
fprintf(stderr, "An Opus encoder cannot be created: %s\n", opus_strerror(opusErr));
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((paErr = Pa_OpenDefaultStream(&aud->stream, channels, channels, paFloat32,
|
if ((paErr = Pa_OpenDefaultStream(&aud->stream, channels, channels, AUDIO_SAMPLE_FORMAT,
|
||||||
sampleRate, frameSize, callback, aud)) != paNoError) {
|
sampleRate, frameSize, NULL, NULL)) != paNoError) {
|
||||||
fprintf(stderr, "Cannot open a PortAudio stream: %s\n", Pa_GetErrorText(paErr));
|
fprintf(stderr, "Cannot open a PortAudio stream: %s\n", Pa_GetErrorText(paErr));
|
||||||
return -1;
|
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) {
|
if ((paErr = Pa_StartStream(aud->stream)) != paNoError) {
|
||||||
fprintf(stderr, "Cannot start a PortAudio stream: %s\n", Pa_GetErrorText(paErr));
|
fprintf(stderr, "Cannot start a PortAudio stream: %s\n", Pa_GetErrorText(paErr));
|
||||||
return -1;
|
return -1;
|
||||||
@ -80,14 +62,55 @@ int audio_destroy(audio_t *aud) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (aud->buffer)
|
||||||
|
free(aud->buffer);
|
||||||
|
|
||||||
if (aud->opusEnc)
|
if (aud->opusEnc)
|
||||||
opus_encoder_destroy(aud->opusEnc);
|
opus_encoder_destroy(aud->opusEnc);
|
||||||
|
|
||||||
if (aud->opusDec)
|
if (aud->opusDec)
|
||||||
opus_decoder_destroy(aud->opusDec);
|
opus_decoder_destroy(aud->opusDec);
|
||||||
|
|
||||||
if (aud->opusBuf)
|
return 0;
|
||||||
free(aud->opusBuf);
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
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;
|
return 0;
|
||||||
}
|
}
|
17
src/audio.h
17
src/audio.h
@ -7,19 +7,22 @@
|
|||||||
#include <opus/opus.h>
|
#include <opus/opus.h>
|
||||||
#include <portaudio.h>
|
#include <portaudio.h>
|
||||||
|
|
||||||
|
#define AUDIO_SAMPLE_FORMAT paFloat32
|
||||||
|
typedef float audio_sample_t;
|
||||||
|
|
||||||
typedef struct audio_t {
|
typedef struct audio_t {
|
||||||
PaStream *stream;
|
PaStream *stream;
|
||||||
OpusEncoder *opusEnc;
|
OpusEncoder *opusEnc;
|
||||||
OpusDecoder *opusDec;
|
OpusDecoder *opusDec;
|
||||||
uint8_t *opusBuf;
|
|
||||||
size_t opusBufSz;
|
audio_sample_t *buffer;
|
||||||
|
size_t bufferSz;
|
||||||
} audio_t;
|
} audio_t;
|
||||||
|
|
||||||
int audio_default_callback(const void *input, void *output,
|
int audio_init(audio_t *aud, int channels, int sampleRate, int frameSize);
|
||||||
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_destroy(audio_t *aud);
|
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_ */
|
#endif /* _AUDIO_H_ */
|
Loading…
Reference in New Issue
Block a user