Make portaudio and speex work together

654 views Asked by At

I am trying to build a minimal loop audio

Microphone -> Portaudio -> buffer -> Speex encoder -> Speex decoder -> buffer -> Portaudio -> Headphones

Without Speex I could get audio with Portaudio and play it in headphones. Inserting Speex encoder/decoder breaks loop audio. I set Portaudio to save audio buffer in a short int* type, as required by Speex Here follows the main loop listing:

#define SAMPLE_RATE  (44100)
#define PA_SAMPLE_TYPE  paInt16
[...]
// initializes Speex
// sets speex_nb_mode for narrow band coding
speex_bits_init(&bits);
enc_state = speex_encoder_init(&speex_nb_mode);
dec_state = speex_decoder_init(&speex_nb_mode);

// gets frame size in samples
int samplesPerFrameEncoder = 0, samplesPerFrameDecoder = 0;
speex_encoder_ctl(enc_state, SPEEX_GET_FRAME_SIZE,
    &samplesPerFrameEncoder);
speex_decoder_ctl(dec_state, SPEEX_GET_FRAME_SIZE,
    &samplesPerFrameDecoder);
if (samplesPerFrameDecoder != samplesPerFrameEncoder)
  throw "Samples per frame between decoder and encoder differ";

// sets quality [0-10]
int quality = 10;
speex_encoder_ctl(enc_state, SPEEX_SET_QUALITY, &quality);

// open a Portaudio stream
error = Pa_OpenStream(&pStream, // reference to pointer to stream variable
    &inputParameters, // reference to input stream properties
    &outputParameters, // reference to output stream properties
    SAMPLE_RATE, // chosen sample rate
    FRAMES_PER_BUFFER, // block granularity for audio sample
    // flags for streaming process. In this case we stream
    // audio sample that never go out of range so we do not
    // clip them
    paClipOff,
    // no callback, use blocking API, input is passed directly
    // to output
    NULL,
    // no callback, so no callback userData
    NULL);
endOnError(pStream, error, pAudioSample);

// starts audio processing
error = Pa_StartStream(pStream);
endOnError(pStream, error, pAudioSample);

char* pSpeexEncodedSample = NULL;
int nbBytes = 0;

while (1)
{
  // TODO decodes audio sample from speex array
  if (nbBytes != 0)
  {
    CLEAR(pAudioSample);
    speex_bits_read_from(&bits, pSpeexEncodedSample, nbBytes);
    speex_decode_int(dec_state, &bits, (short*) pAudioSample);
    // writes audio sample to output stream
    error = Pa_WriteStream(pStream, // pointer to stream variable
        pAudioSample, // pointer to audio sample
        FRAMES_PER_BUFFER // block granularity for audio sample
        );
  }
  // reads audio sample from input stream
  error = Pa_ReadStream(pStream, // pointer to stream variable
      pAudioSample, // pointer to audio sample
      FRAMES_PER_BUFFER // block granularity for audio sample
      );
  // TODO codes audio sample to speex array
  speex_bits_reset(&bits);
  speex_encode_int(enc_state, (short*) pAudioSample, &bits);
  int bytesRequired = speex_bits_nbytes(&bits);
  if (pSpeexEncodedSample != NULL)
  {
    free(pSpeexEncodedSample);
    pSpeexEncodedSample = NULL;
  }
  pSpeexEncodedSample = (char*) malloc(
      bytesRequired * sizeof(char));
  nbBytes = speex_bits_write(&bits, pSpeexEncodedSample,
      bytesRequired);
}
[...]

Thanks

0

There are 0 answers