阅读 229

音视频 day12播放WAV_录制WAV_录音时长

1. 下面两种方式,都能获取一个 AVPacket 实例对象,请问有什么不同?如何取舍呢?

AVPacket pkt; // 方式一
AVPacket *pkt2 = av_packet_alloc(); // 方式二
复制代码
  • AVPacket pkt; 是在栈空间创建了一个实例对象 pkt
  • AVPacket *pkt2 = av_packet_alloc();pkt2 这个指针在栈空间,而 pkt2 所指向的实例对象堆空间
  • 取舍:如果实例对象所需要的内存比较大时,建议使用方法二,将实例对象放在堆空间,因为栈空间的大小比较有限

2. 在 C 语言或者 C++中的方法,经常返回值是 0 或者负数,请问分别代表什么?

  • 这种方法常常存在于对资源调度的方法,0通常表示成功,负数通常表示失败。
  • 负数的具体值,比如 -1、-2 则是错误的具体错误码

3. 使用 SDL 播放 WAV 文件,核心代码如下

// 音频参数
SDL_AudioSpec spec;
// 指向 PCM 数据
Uint8 *data = nullptr;
// PCM 数据长度
Uint32 len = 0;
// 调用 SDL_LoadWAV 方法,对 WAV 进行解析,获得采样率、声道、采样格式等参数数据
if (!SDL_LoadWAV(FILENAME, &spec, &data, &len)) {
 qDebug() << "SDL_LoadWAV error" << SDL_GetError();
 // 清除所有的子系统
 SDL_Quit();
 return;
}
复制代码

4. file.write(&data,len)file.seek(sizeof(WAVHeader)) 这两个函数有什么作用?

  • file.write(&data,len) , 是将 data 中的数据取 len 长度,并写入文件流中,默认是写到文件尾部
  • file.seek(sizeof(WAVHeader)),是将 file 写入位置定位到 sizeof(WAVHeader),配合file.write(&data,len)可以修改指定数据

5. 代码录音,直接生成 WAV 文件,说一下核心思想?

  • 核心思想:先往文件头部写入 WAVHeader数据,然后写入 PCM 数据,最后修正 WAVHeader数据 中的 ChunkSize 和 PCMSize 即可。
file.seek(sizeof (WAVHeader) - sizeof (header.dataChunkDataSize));
file.write((char *) &header.dataChunkDataSize, sizeof (header.dataChunkDataSize));

// 写入riffChunkDataSize
header.riffChunkDataSize = file.size() - sizeof (header.riffChunkId) - sizeof (header.riffChunkDataSize);
file.seek(sizeof (header.riffChunkId));
file.write((char *) &header.riffChunkDataSize, sizeof (header.riffChunkDataSize));

复制代码

6. 展示录音时长的核心思想是什么?

  • 核心思想:子线程根据录制的 PCM 数据算出录音时长 → 子线程发射信号 → 主线程槽接收信号,更新展示时间
// 计算录音时长
header.dataChunkDataSize += pkt.size;
unsigned long long ms = 1000.0 * header.dataChunkDataSize / header.byteRate;
emit timeChanged(ms);
复制代码

7. 立体声的样本帧,在 PCM 中是如何排布的?

image.png

8. 正常的 PCMPlanar 版本的 PCM 有什么区别?

  • 正常的 PCM 是左右声道为一个样本帧
  • Planar 版本的 PCM 左右声道分开存储,左声道于左声道连续,右声道于右声道连续

image.png

文章分类
iOS
文章标签