我在使用带有端口音频的opus时遇到问题。
我需要使用PortAudio从流中读取数据音频、编码数据、解码数据和写入数据。如果我只是读和写,一切都很好。但在编码和解码时,我能听到的只是背景中有我的声音的雪。
以下是我的部分代码:
I/O流头:
#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;
};
I/O流.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); }
我真的很需要你,非常感谢你抽出时间来帮助我。
最佳答案
#define PA_SAMPLE_TYPE paInt24
那可能是你的问题。据我所知,标准OPUS编解码器采用16位整数或32位浮点采样。这些对应于PortAudio示例类型paInt16和paFloat32。
我建议你把所有样本缓冲区的类型都弄对。对格式化的样本数据使用unsigned char*会带来麻烦。您需要了解PortAudio函数和OPUS编解码器函数所期望的数据类型。
关于c++ - 将Opus与PortAudio结合使用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20708965/