Использование Opus с PortAudio

У меня проблемы с использованием опуса с портом аудио.
Мне нужно прочитать данные аудио из потока, используя PortAudio, кодирование данных, декодирование данных и запись данных. Если я просто читаю и пишу, все работает хорошо. Но при кодировании и декодировании все, что я слышу, — это снег с фоном голоса.
Вот часть моего кода:

Заголовок потока ввода / вывода:

#define NUM_CHANNELS    (2)
#define PA_SAMPLE_TYPE  paInt24
#define SAMPLE_RATE  (48000)
#define FRAMES_PER_BUFFER (1024)
#define SAMPLE_SIZE (3)
#define FRAME_SIZE (960)

class                           SoundSystem
{

private:
PaStream                      *_stream;
int                           _readBufferSize;
PaStreamParameters            _inputParam;
PaStreamParameters            _outputParam;
unsigned char                         *_readBuffer;

public:
SoundSystem();
~SoundSystem();

// Init Stream
bool                          initPa();
bool                          openStream();
bool                          startStream();
bool                          initStream();

// Init params stream
bool                          initParams() const;
bool                          initInputParams();
bool                          initOutputParams();
bool                          initParams();

// I/O
bool                          writeOnStream(unsigned cha\
r *buff);
bool                          readFromStream();

// Utils
void                          cleanReadBuffer();
int                           getReadBufferSize() const;
unsigned char                 *getReadBuffer() const;

};

Поток ввода / вывода .cpp:

SoundSystem::SoundSystem()
{
_stream = NULL;
_readBufferSize = FRAMES_PER_BUFFER * NUM_CHANNELS * SAMPLE_SIZE;
_readBuffer= new unsigned char [_readBufferSize];
}

SoundSystem::~SoundSystem()
{
}

bool            SoundSystem::initPa()
{
if ((Pa_Initialize()) != paNoError)
return (false);
return (true);
}

bool            SoundSystem::openStream()
{
if ((Pa_OpenStream(&_stream, &_inputParam, &_outputParam, SAMPLE_RATE,
FRAMES_PER_BUFFER, paClipOff, NULL, NULL)) != paNoError)
return (false);
return (true);
}

bool            SoundSystem::startStream()
{
if ((Pa_StartStream(_stream)) != paNoError)
return (false);
return (true);
}

bool            SoundSystem::initStream()
{
if ((openStream()) == false)
std::cerr << "can not open stream" << std::endl;
if ((startStream()) == false)
std::cerr << "cannot start stream" <<std::endl;
return (true);
}

bool            SoundSystem::initParams()
{
if ((initPa()) == false)
std::cerr << "can not ijnit PA" << std::endl;
initInputParams();
initOutputParams();
return (true);
}

bool            SoundSystem::initInputParams()
{
if ((_inputParam.device = Pa_GetDefaultInputDevice()) == paNoDevice)
return (false);
_inputParam.channelCount = 2;
_inputParam.sampleFormat = PA_SAMPLE_TYPE;
_inputParam.suggestedLatency = Pa_GetDeviceInfo(_inputParam.device)->defaultLowInputLatency;
_inputParam.hostApiSpecificStreamInfo = NULL;
return (true);
}

bool            SoundSystem::initOutputParams()
{
if ((_outputParam.device = Pa_GetDefaultInputDevice()) == paNoDevice)
return (false);
_outputParam.channelCount = 2;
_outputParam.sampleFormat = PA_SAMPLE_TYPE;
_outputParam.suggestedLatency = Pa_GetDeviceInfo(_outputParam.device)->defaultLowInputLatency;
_outputParam.hostApiSpecificStreamInfo = NULL;
return (true);
}

bool            SoundSystem::writeOnStream(unsigned char *buff)
{
if ((Pa_WriteStream(_stream, buff, FRAMES_PER_BUFFER)) != paNoError)
{
std::cout << "FAIL WRITE" <<std::endl;
return (false);
}
return (true);
}

bool            SoundSystem::readFromStream()
{
if ((Pa_ReadStream(_stream, _readBuffer, FRAMES_PER_BUFFER)) != paNoError)
return (false);
return (true);
}

void            SoundSystem::cleanReadBuffer()
{
for (int i = 0; i != _readBufferSize; i++)
_readBuffer[i] = 0;
}

int             SoundSystem::getReadBufferSize() const
{enter code here
return (_readBufferSize);
}

unsigned char*          SoundSystem::getReadBuffer() const { return (_readBuffer); }

Заголовок кодирования:

#define FRAME_SIZE (960)
#define SAMPLE_RATE (48000)
#define CHANNELS (2)
#define APPLICATION OPUS_APPLICATION_VOIP

#define MAX_FRAME_SIZE (6*960)

class                           EncoderSystem
{

private:
OpusEncoder                   *_encode;
OpusDecoder                   *_decode;

opus_int16                    _in[FRAME_SIZE*CHANNELS];
opus_int16                    _out[MAX_FRAME_SIZE*CHANNELS];
int                           _nbBytes;public:
EncoderSystem();
~EncoderSystem();

bool                          encoderCreate();
bool                          decoderCreate();

unsigned char*                encode(unsigned char *, int);
unsigned char*                decode(unsigned char *, int);

int                           getEncodeLen() const;

};

Кодировать .cpp:

EncoderSystem::EncoderSystem()
{
}

EncoderSystem::~EncoderSystem()
{
}

bool            EncoderSystem::encoderCreate()
{
int           error;

if ((_encode = opus_encoder_create(SAMPLE_RATE, CHANNELS, OPUS_APPLICATION_VOIP, &error)) == NU\
LL)
{
std::cerr << "Can not create encode" <<std::endl;
return (false);
}
return (true);
}

bool            EncoderSystem::decoderCreate()
{
int           error;

if ((_decode = opus_decoder_create(SAMPLE_RATE, CHANNELS, &error)) == NULL)
{
std::cerr << "Can not create decoder" <<std::endl;
return (false);
}
return (true);
}

unsigned char*          EncoderSystem::encode(unsigned char *data, int size)
{
unsigned char         *c_bits = new unsigned char [size];

memcpy(_in, data, size);

/* Encode the frame. */
_nbBytes = opus_encode(_encode, _in, FRAME_SIZE, c_bits, size);
if (_nbBytes<0)
{
std::cerr << "cannot decode" << std::endl;
return NULL;
}
return (c_bits);
}
unsigned char*          EncoderSystem::decode(unsigned char *data, int size)
{

int   frame_size = opus_decode(_decode, data, size, _out,
MAX_FRAME_SIZE * CHANNELS * 2, 0);
unsigned char         *pcm_bytes = new unsigned char [MAX_FRAME_SIZE * CHANNELS * 2];

if (frame_size<0)
{
std::cerr << "cannot decode" << std::endl;
return (NULL);
}
memcpy(pcm_bytes, _out, size);

return (pcm_bytes);
}

int             EncoderSystem::getEncodeLen() const { return (this->_nbBytes); }

Ты мне действительно нужен, большое спасибо, что уделили мне время.

1

Решение

#define PA_SAMPLE_TYPE paInt24

Это, вероятно, ваша проблема. Насколько я знаю, стандартные кодеки OPUS берут 16-разрядные целые числа или 32-разрядные выборки с плавающей запятой. Они соответствуют типам образцов PortAudio paInt16 и paFloat32.

Я рекомендую получить правильные типы всех ваших буферов сэмплов. Использование unsigned char * для форматированных данных образца вызывает проблемы. Вам необходимо понять, какие типы данных ожидаются функциями PortAudio и функциями кодека OPUS.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]