【问题标题】:Decoding with Opus API using opus_decode_float使用 opus_decode_float 使用 Opus API 进行解码
【发布时间】:2017-03-14 19:14:20
【问题描述】:

我正在尝试将 OPUS api 的基本编码和解码功能与这个 main 一起使用:

#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <opus/opus.h>
#include <stdio.h>

int     main(int argc, char **argv)
{
  OpusEncoder   *enc;
  OpusDecoder   *dec;
  unsigned char         *str;
  float         frame = 0.32;
  int           ret = 0;
  int           error;
  float         *returned;

  if ((str = malloc(4096)) == NULL)
    return (-1);
  enc = opus_encoder_create (24000, 1, OPUS_APPLICATION_AUDIO, &error);

  printf("ret = %d | input = %.2f\n", error, frame);

  ret = opus_encode_float(enc, &frame, 480, str, 4096);

  printf("ret = %d\n", ret);

  dec = opus_decoder_create (24000, 1, &error);
  ret = opus_decode_float(dec, str, ret, returned, 480, 0);

  printf("ret = %d | res = %.2f\n", ret, returned[0]);

  return (0);
}

问题是我试图在编码中传递 0.32 浮点数并使用 opus_decoder_float 对其进行解码,但是当我试图打印我的结果时,我只得到 0.00 并且我找不到任何使用示例具体功能。

我没有收到任何有关 ret 值的错误消息,程序打印:

ret = 0 | input = 0.32
ret = 3
ret = 480 | res = 0.00

如何在返回的浮点数中获得 0.32?

【问题讨论】:

  • 建议检查返回值,如enc 和dec。

标签: c opus


【解决方案1】:

Opus 具有 2.5 到 6.5 毫秒的前瞻时间,具体取决于编码器参数。因此,与输入相比,解码的输出会稍微延迟,对于样本精确的解码,您应该跳过解码器中的那些初始样本,并在最后解码相同数量的额外样本。可以使用以下方法获得前瞻样本的确切数量:

opus_int32 skip;
opus_encoder_ctl(enc, OPUS_GET_LOOKAHEAD(&skip));

这意味着您应该跳过第一个skip 解码样本以获取与输入的第一个样本相对应的样本。

还要记住,它是有损压缩。虽然它旨在让人类听众听起来与原始声音相同,但您不应期望样本的值相同。

【讨论】:

    【解决方案2】:

    returned 未初始化。 opus_decode_float() 和 printf() 接收到一个具有不确定值的指针。

      // problem code
      returned  float         *returned;  
      ...
      // What value is `returned`?
      ret = opus_decode_float(dec, str, ret, returned, 480, 0);
      printf("ret = %d | res = %.2f\n", ret, returned[0]);
    

    建议修复,分配内存。 opus_decode_float()

      returned  float         *returned;
      ...
      int frame_size = 480;
      int channels = 1;  // from `opus_encoder_create (24000, 1, ...`
    
      returned = malloc(sizeof *returned * frame_size * channels);
      assert(returned);
      ret = opus_decode_float(dec, str, ret, returned, frame_size, 0);
    
      printf("ret = %d | res = %.2f\n", ret, returned[0]);
      free(returned);
    

    此外,当我阅读doc 时,下面的pcm 需要一个指向float (frame_size*channels) 的大数组的指针,而不仅仅是1。

    opus_int32 opus_encode_float(OpusEncoder *st, const float *pcm,
        int frame_size, unsigned char *data, opus_int32 max_data_bytes) 
    
    // Too small?
    float frame = 0.32;
    ret = opus_encode_float(enc, &frame, 480, str, 4096);
    

    【讨论】:

    • 这可能是个麻烦,尽管即使我按照所说的分配浮点数,最后我仍然得到 0.00。
    • @S.Hochberg 注意:代码有许多幻数,例如 4096、24000、1,没有不言自明的含义——这增加了理解代码的难度。示例:最好在各个地方使用int frame_size = 480; 和frame_size 之类的东西,而不是480,以清楚地传达对象的含义。 AFAIK 4096 是错误的。为什么是 4096?
    • 好吧,他们需要缓冲区的大小,所以出于测试目的,我并没有想太多,只是将其设置为 4096。24000 和 1 是 Opus API 询问的与采样率相对应的数字输入信号的数量和通道数(1对应单声道和2立体声)
    • @S.Hochberg 我知道这些值的用途以及它们的需要,在查找它们之后 - 但这需要时间。如前所述,使代码不言自明、自文档化有助于审阅者更好地理解并专注于问题。
    猜你喜欢
    • 2015-08-07
    • 1970-01-01
    • 1970-01-01
    • 2019-01-09
    • 2015-01-18
    • 2013-12-31
    • 1970-01-01
    • 2018-08-31
    • 1970-01-01
    相关资源
    最近更新 更多