swr_get_out_samples和swr_convert,比特率重采样

简介: swr_get_out_samples和swr_convert,比特率重采样

音频三元组:通道数(channels,比特率(sample_rate),位深(sample_fmt)

这三个元素转换一个或以上,就叫作重采样。

这里主要讨论48000->44100可能会犯得错误。

swr_convert(asc, dst_ptr, dst_nb_samples,
              src_ptr, src_nb_samples)


参数依次是重采样配置上下文,接收转换后的数据存储地址,往dst_data存储多少个音频采样,待转换的数据地址,放入转换的音频采样数。

假如说是48000->44100,那么如果放入的src_nb_samples不是48000,那么取出的dst_nb_samples也就不是44100,是多少呢:

44100/48000 = dst_nb_samples/src_nb_samples


另一个问题,假如我用aac压缩音频,aac规定每帧音频只能有1024个采样,如果放入src_nb_samples是1920,那么按照上面的公式dst_nb_samples=1764。但是我每次只取1024个采样,用于压缩aac,那么没取的1764-1024=76个字节放哪里去了呢,会不会丢失呢,它其实放在了swr_convert这个函数维护的一个缓冲区中,当你再次调用swr_convert(asc, dst_ptr, dst_nb_samples, NULL, 0)时,把后两个参数置NULL,0,就会把上次没取完的数据取出dst_nb_samples(如果有这么多的话)个采样,它其实是个队列的原理。


最后一个问题,swr_get_out_samples(…)的返回值是缓冲区中的采样个数,那么这个值是指转换后的采样个数还是转换前的呢,经手动验证是转换前的。其实也就是函数只转换dst_nb_samples个采样输出,剩余的值下次调用再转换。

假如我们想取1024个值,那么应该这样调用:

int fifo_size = swr_get_out_samples(asc, 0);
if (fifo_size >= 1115) //x = (1920/1764) * 1024
{
  int len_left = swr_convert(asc, dst_ptr, dst_nb_samples,
            NULL, 0)
}


意思是48000->44100时,只有缓冲区有1115个采样时,才能得到1024个采样。

当44100->48000时,当送进去1024采样时,理论上会得到1114.5个输出采样,那么我们输出dst_nb_samples参数应该填多少呢,只要大于等于1115,就可以了,实测输出的采样数len = 1115,1114交替输出。

当dst_nb_samples大于理论输出值时,并不会阻塞,等得到dst_nb_samples个采样才输出,而是输出理论值,由len返回获得理论值。

int len = swr_convert(asc, dst_ptr, dst_nb_samples,

src_ptr, src_nb_samples)


补充:


正常人听觉的频率范围大约在20Hz~20kHz之间,

根据奈奎斯特采样理论(2倍),为了保证声音不失真,采样频率应该在40kHz左右。(采样频率必须大于等于音频信号的最大频率的两倍,记住,是最大频率。)

目前语音识别服务只支持16000Hz和8000Hz两种采样率,其中8000Hz一般是电话业务使用,其余都使用16000Hz。 22050

的采样频率是常用的,44100已是CD音质。

44100 Hz - 音频 CD, 也常用于 MPEG-1 音频(VCD,SVCD,MP3)所用采样率
48000 Hz - miniDV、数字电视、DVD、DAT、电影和专业音频所用的数字声音所用采样率
8000 Hz - 电话所用采样率, 对于人的说话已经足够
22050 Hz - 无线电广播所用采样率   
引用链接:https://blog.csdn.net/Osean_li/article/details/84107451


出于历史原因,所有CD一律采用44.1KHz,而DVD/BD视频音轨一律采用48KHz。所以不出意外,你听到的那些音乐都是44.1KHz,而你看的视频,它们的音频一般都采用48KHz的采样率。

aac为有损压缩,同时48000->44100的转换对音质也有损伤。

由于人耳听觉范围是20Hz~20kHz,根据香农采样定理(也叫奈奎斯特采样定理),理论上来说采样率大于40kHz的音频格式都可以称之为无损格式。

我们的耳朵听到的频率间隔为20-20KHZ,我们的发声频率为100-3KHZ左右,所以可以看出如果只是单纯的采集发声频率可以使用8KHZ就可以,采样率必须是输入信号最高频率的2倍以上,这样才会最大可能的保存信号信息.故我们的听到的样本的采样率一般都为44.1KHZ及以上.

fdk_aac 支持的音频采样率:7350 8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000

fdk_aac 样本类型:只支持16bit pcm输入.

CBR模式:

设置目标码率,当样本之间差异较小时,可以通过该方法更好地控制文件大小,设置每个通道为64kbps.立体声为128kbps

VBR模式:

指定目标质量,而不是码率,质量从1到5由低到高.使用参数-vbr,vbr模式下大致给出了每个通道对应的码率,参考libfdk_aac介绍

首先需要了解的是AAC文件格式有ADIF和ADTS两种,其中ADIF(Audio Data Interchange Format 音频数据交换格式)的特征是解码必须在明确定义的开始处进行,不能从数据流中间开始;而ADTS(Audio Data Transport Stream 音频数据传输流)则相反,这种格式的特征是有同步字,解码可以在这个流中任何位置开始,正如它的名字一样,这是一种和TS流类似的格式。


ADTS格式中每一帧都有头信息,具备流特征,适合于网络传输与处理,而ADIF只有一个统一的头,并且这两种格式的header格式也是不同的。目前主流使用的都是ADTS格式。

正确的说法是不同profile决定了每个aac帧含有多少个sample,具体来说,对应关系如下:


AACENC_GRANULE_LENGTH =

0x0105, /*!< Core encoder (AAC) audio frame length in samples:

- 2048 HE-AAC v1/v2

- 1024: Default configuration.//AAC-LC 1024

- 512: Default length in LD/ELD configuration.

- 480: Length in LD/ELD configuration.

- 256: Length for ELD reduced delay mode (x2).

- 240: Length for ELD reduced delay mode (x2).

- 128: Length for ELD reduced delay mode (x4).

- 120: Length for ELD reduced delay mode (x4). */

其中LC即Low Complexity,HE即High Efficiency,注意,其中数据表示单通道的采样数,如1024,表示单通道每秒采样1024帧。每次送入编码器的数据必须是上述设定或默认的数据,如果不是的话会在缓冲区中暂存,然后够了之后再送进去。

声道数:

0: Defined in AOT Specifc Config

1: 1 channel: front-center

2: 2 channels: front-left, front-right

3: 3 channels: front-center, front-left, front-right

4: 4 channels: front-center, front-left, front-right, back-center

5: 5 channels: front-center, front-left, front-right, back-left, back-right

6: 6 channels: front-center, front-left, front-right, back-left, back-right, LFE-channel

7: 8 channels: front-center, front-left, front-right, side-left, side-right, back-left, back-right, LFE-channel

8-15: Reserved

SwrContext * asc = NULL;
  asc = swr_alloc_set_opts(asc,
               AV_CH_LAYOUT_STEREO, (AVSampleFormat)a_frame->format, a_frame->sample_rate,
               AV_CH_LAYOUT_STEREO, (AVSampleFormat)a_frame->format, 48000, 0, 0);
  if (!asc)
  {
    printf("swr_alloc_set_opts failed!\n");
    return -1;
  }
  int ret_asc = swr_init(asc);
  if (ret_asc != 0)
  {
    printf("swr_init failed!\n");
    char err[1024] = {0};
    av_strerror(ret_asc, err, sizeof(err) - 1);
    return -1;
  }
  int fifo_size_1 = swr_get_out_samples(asc, 0);
  int len = swr_convert(asc, a_frame->data, a_frame->nb_samples,
              indata, frame_num);
    if (len >= 1024)
  {//....
  }
/*
  int fifo_size_2 = swr_get_out_samples(asc, 0);
  if (fifo_size_2 >= 1115) //x = (1920/1764) * 1024
  {
    int len_left = swr_convert(asc, a_frame->data, a_frame->nb_samples,
                   NULL, 0);
    if (len_left >= 1024)
    {//...
    }
  }
*/



相关文章
|
1月前
|
TensorFlow 算法框架/工具
Tensorflow error(二):x and y must have the same dtype, got tf.float32 != tf.int32
本文讨论了TensorFlow中的一个常见错误,即在计算过程中,变量的数据类型(dtype)不一致导致的错误,并通过使用`tf.cast`函数来解决这个问题。
23 0
|
3月前
|
TensorFlow 算法框架/工具 Python
利用tf.convert_to_tensor转换为类型
【8月更文挑战第11天】利用tf.convert_to_tensor转换为类型。
59 9
|
3月前
|
计算机视觉
OpenCV 图像类型标识符 CV_<bit_depth><S|U|F>C<number_of_channels>
OpenCV 图像类型标识符 CV_<bit_depth><S|U|F>C<number_of_channels>
38 0
|
5月前
|
算法 计算机视觉
【Qt&OpenCV 直方图计算 split/calcHist/normalize】
【Qt&OpenCV 直方图计算 split/calcHist/normalize】
48 0
|
6月前
|
计算机视觉
halcon系列基础之Scale_image_range
halcon系列基础之Scale_image_range
306 0
paraformer支持设置 speech_noise_threshold 这个参数吗 ?
请问:speech_paraformer-large-vad-punc_asr_nat-zh-cn-16k-common-vocab8404-pytorch 这个模型支持设置 speech_noise_threshold 这个参数吗 ? vad 本身是支持的,但对这个集成的模型好像不起作用? 如果支持,应该如何正确地设置呢 ? 如果不支持,那该模型有没有什么方法可以过滤掉背景噪声? 经常会有背景噪声被识别出文字
61 0
paraforme支持speech_noise_threshold吗?
请问:speech_paraformer-large-vad-punc_asr_nat-zh-cn-16k-common-vocab8404-pytorch 这个模型支持设置 speech_noise_threshold 这个参数吗 ? vad 本身是支持的,但对这个集成的模型好像不起作用? 如果支持,应该如何正确地设置呢 ? 如果不支持,那该模型有没有什么方法可以过滤掉背景噪声? 经常会有背景噪声被识别出文字
53 0
一张图深入的理解FP/FN/Precision/Recall
一张图深入的理解FP/FN/Precision/Recall
209 0
|
机器学习/深度学习 算法
随机装箱特征模型(Random Binning Feature Model)代码
在上述代码中,我们首先定义了一个名为RandomBinningFeatureModel的类,并在其__init__方法中接受一个参数num_bins,表示装箱的数量。然后,我们定义了一个名为fit_transform的方法,该方法接受原始输入数据x作为参数,并返回转换后的特征张量xb。
157 0
|
机器学习/深度学习 自然语言处理 Python
Word2Vec教程-Negative Sampling 负采样
这篇word2vec教程2中(教程1 Word2Vec教程-Skip-Gram模型),作者主要讲述了skip-gram 模型优化的策略-Negative Sampling,使得模型更加快速地训练。通过教程1,我们了解到word2vec它是一个庞大的神经忘网络! 例如,有一个包含10000个单词的词汇表,向量特征为300维,我们记得这个神经网络将会有两个weights矩阵----一个隐藏层和一个输出层。这两层都会有一个300x10000=3000000的weight矩阵。 在如此大的神经网络上进行梯度下降是非常慢的,更加严重的是,我们需要大量训练数据去调整weights和避免over-fitti
727 0
Word2Vec教程-Negative Sampling 负采样