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

0

У меня возникли проблемы с использованием opus с портом аудио. Мне нужно прочитать аудиоданные данных из потока, используя 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;

};

Encode.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); }

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

  • 0
    Не совсем уверен, в чем проблема, но у вас потенциально есть пара больших утечек памяти в EncoderSystem :: encode и EncoderSystem :: decode - вы не освобождаете выделенные буферы. Это также проблема производительности - было бы лучше распределить буферы один раз по мере необходимости (или, если они должны расти). Возможно, вам лучше иметь поток кодирования / декодирования, в который вы можете вставлять аудиоданные, что также обрабатывает ситуацию, когда количество аудиосэмплов не является точным кратным размеру кадра.
Теги:
portaudio
opus

1 ответ

0

#define PA_SAMPLE_TYPE paInt24

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

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню