マイク → speexエンコーダ → speexデコーダ → スピーカー
だけの。
speexエンコーダ、speexデコーダ無しだと問題ないところ、ありにすると、
なんか高音のノイズが入るのはなぜ?
speex-devのMLに質問中。。。
コードはこんな
[cpp]
include “stdafx.h”
include
include
include #include
include
define USE_SPEEX
define SAMPLE_RATE (44100)
define FRAMES_PER_BUFFER (256)
define NUM_SECONDS (10)
//#define NUM_CHANNELS (2)
define NUM_CHANNELS (1) // try mono first
/* #define DITHER_FLAG (paDitherOff) */
define DITHER_FLAG (0) /**/
/* Select sample format. */
define PA_SAMPLE_TYPE paFloat32
typedef float SAMPLE;
define SAMPLE_SILENCE (0.0f)
define PRINTF_S_FORMAT “%.8f”
typedef struct {
int frameIndex; /* Index into sample array. */
int maxFrameIndex;
std::queue
std::queue
std::queue
} paTestData;
// speex globals
SpeexBits encoder_bits;
SpeexBits decoder_bits;
void encoder_state;
void decoder_state;
unsigned int speex_frame_size; // 320 or 640 or ..
unsigned int speex_packet_size = 74; // 74 or something
/ This routine will be called by the PortAudio engine when audio is needed.
It may be called at interrupt level on some machines so don’t do anything
that could mess up the system like calling malloc() or free().
/
static int echo( 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;
SAMPLE *wptr = (SAMPLE*)outputBuffer;
ifdef USE_SPEEX
std::queue
std::queue
std::queue
else
std::queue
//std::queue
std::queue
endif
long framesToCalc;
long i;
int finished;
unsigned long framesLeft = data->maxFrameIndex – data->frameIndex;
if( framesLeft < framesPerBuffer ) {
framesToCalc = framesLeft;
finished = paComplete;
}
else {
framesToCalc = framesPerBuffer;
finished = paContinue;
}
// process input from mic
if( rptr == 0 ) {
}
else {
for( i=0; i<framesToCalc; i++ ) {
qu_microphone.push( rptr++ );
if ( NUM_CHANNELS == 2 ) {
qu_microphone.push( rptr++ );
}
}
}
ifdef USE_SPEEX
// speex encoder
while ( qu_microphone.size() > speex_frame_size ) {
float input[1000];
char encoded[1000];
for ( unsigned int i=0; i<speex_frame_size ; i++ ) {
input[i] = qu_microphone.front(); qu_microphone.pop();
}
speex_bits_reset( &encoder_bits );
speex_encode( encoder_state, input, &encoder_bits );
speex_packet_size = speex_bits_write( &encoder_bits, encoded, 1000 );
for ( unsigned int i=0; i<speex_packet_size; i++ ) {
qu_speex.push( encoded[i] );
}
}
// speex decoder
while ( qu_speex.size() >= speex_packet_size ) {
float output[1000];
char encoded[1000];
int nbBytes = speex_packet_size;
for ( int i=0; i<nbbytes ; i++ ) {
encoded[i] = qu_speex.front(); qu_speex.pop();
}
speex_bits_read_from( &decoder_bits, encoded, nbBytes );
speex_decode( decoder_state, &decoder_bits, output );
for ( unsigned int i=0; i<speex_frame_size; i++ ) {
qu_speaker.push( output[i] );
}
}
endif
// pop to speaker
for( i=0; i
wptr++ = qu_speaker.front(); qu_speaker.pop();
}
else {
wptr++ = SAMPLE_SILENCE;
}
if( NUM_CHANNELS == 2 ) {
if ( qu_speaker.size() > 0 ) {
wptr++ = qu_speaker.front(); qu_speaker.pop();
}
else {
wptr++ = SAMPLE_SILENCE;
}
}
}
data->frameIndex += framesToCalc;
return finished;
}
/**********************/
int main(void)
{
PaStreamParameters inputParameters,
outputParameters;
PaStream stream;
PaError err = paNoError;
int totalFrames;
std::cout < < “patest_record.c”;
paTestData data;
data.maxFrameIndex = totalFrames = NUM_SECONDS * SAMPLE_RATE; /* Record for a few seconds. */
data.frameIndex = 0;
int numSamples = totalFrames * NUM_CHANNELS;
int numBytes = numSamples * sizeof(SAMPLE);
int tmp;
// encoder
encoder_state = speex_encoder_init( speex_lib_get_mode(SPEEX_MODEID_UWB) );
tmp=0;
speex_encoder_ctl(encoder_state, SPEEX_SET_VBR, &tmp);
tmp=8;
speex_encoder_ctl(encoder_state, SPEEX_SET_QUALITY, &tmp); // 8: 27,800[bps]
tmp=3;
speex_encoder_ctl(encoder_state, SPEEX_SET_COMPLEXITY, &tmp);
// 320[samples] = 20ms? according to http://www.speex.org/docs/manual/speex-manual/node7.html
speex_encoder_ctl( encoder_state, SPEEX_GET_FRAME_SIZE, &speex_frame_size );
speex_bits_init( &encoder_bits );
// decoder
decoder_state = speex_decoder_init( speex_lib_get_mode(SPEEX_MODEID_UWB) );
SpeexCallback callback;
callback.callback_id = SPEEX_INBAND_CHAR;
callback.func = speex_std_char_handler;
callback.data = stderr;
speex_decoder_ctl(decoder_state, SPEEX_SET_HANDLER, &callback);
tmp=1;
speex_decoder_ctl(decoder_state, SPEEX_SET_ENH, &tmp);
speex_bits_init( &decoder_bits );
err = Pa_Initialize();
if( err != paNoError ) goto done;
inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
if (inputParameters.device == paNoDevice) {
fprintf(stderr,“Error: No default input device.\n”);
goto done;
}
inputParameters.channelCount = NUM_CHANNELS; /* stereo input */
inputParameters.sampleFormat = PA_SAMPLE_TYPE;
inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
inputParameters.hostApiSpecificStreamInfo = 0;
outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
if (outputParameters.device == paNoDevice) {
fprintf(stderr,”Error: No default output device.\n”);
goto done;
}
outputParameters.channelCount = NUM_CHANNELS; /* stereo output */
outputParameters.sampleFormat = PA_SAMPLE_TYPE;
outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
outputParameters.hostApiSpecificStreamInfo = 0;
/* start echo ——————————————– */
err = Pa_OpenStream(
&stream,
&inputParameters,
&outputParameters,
SAMPLE_RATE,
FRAMES_PER_BUFFER,
paClipOff, /* we won’t output out of range samples so don’t bother clipping them */
echo,
&data );
if( err != paNoError ) goto done;
err = Pa_StartStream( stream );
if( err != paNoError ) goto done;
printf(“Now recording!!\n”); fflush(stdout);
while( ( err = Pa_IsStreamActive( stream ) ) == 1 )
{
Pa_Sleep(1000);
printf(“index = %d\n”, data.frameIndex ); fflush(stdout);
}
if( err < 0 ) goto done;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto done;
done:
// destruct speex
speex_encoder_destroy( encoder_state );
speex_bits_destroy( &encoder_bits );
speex_decoder_destroy( decoder_state );
speex_bits_destroy( &decoder_bits );
Pa_Terminate();
if( err != paNoError )
{
fprintf( stderr, “An error occured while using the portaudio stream\n” );
fprintf( stderr, “Error number: %d\n”, err );
fprintf( stderr, “Error message: %s\n”, Pa_GetErrorText( err ) );
err = 1; /* Always return 0 or 1, but no other return codes. */
}
return err;
}
[/cpp]