鸿蒙Next中PCM怎么转成WAV

在鸿蒙Next系统中,如何将PCM音频数据转换成WAV格式?有没有现成的API或库可以直接调用?如果需要手动实现,转换的具体步骤和注意事项是什么?最好能提供代码示例或相关文档参考。

2 回复

鸿蒙Next里PCM转WAV?简单!先给WAV文件写个44字节的文件头,包含采样率、声道数等参数,然后把PCM数据直接塞进去。就像给裸奔的数据穿条裤子——WAV头就是那条遮羞裤!记得用ohos.file.fs操作文件,别把裤子穿反了。

更多关于鸿蒙Next中PCM怎么转成WAV的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在鸿蒙Next(HarmonyOS NEXT)中,将PCM音频数据转换为WAV格式可以通过以下步骤实现:

1. 理解PCM和WAV格式

  • PCM:原始音频数据,不包含文件头信息。
  • WAV:在PCM数据前添加WAV文件头(包含采样率、声道数、位深度等)。

2. 转换步骤

  1. 读取PCM数据:从文件或音频流获取PCM原始数据。
  2. 构建WAV文件头:根据PCM参数生成标准的44字节WAV头。
  3. 合并数据:将WAV头与PCM数据拼接,生成完整WAV文件。

3. 代码示例(TypeScript/ArkTS)

import fs from '@ohos.file.fs';
import buffer from '@ohos.buffer';

// WAV文件头结构(44字节)
class WavHeader {
  private static readonly HEADER_SIZE = 44;

  static createHeader(
    sampleRate: number,   // 采样率(如44100)
    channels: number,     // 声道数(1单声道,2立体声)
    bitsPerSample: number,// 位深度(如16)
    dataSize: number      // PCM数据大小(字节)
  ): Uint8Array {
    const buffer = new ArrayBuffer(WavHeader.HEADER_SIZE);
    const dataView = new DataView(buffer);

    // RIFF头
    dataView.setUint32(0, 0x52494646, false); // "RIFF"
    dataView.setUint32(4, 36 + dataSize, true); // 文件总大小-8
    dataView.setUint32(8, 0x57415645, false); // "WAVE"

    // fmt子块
    dataView.setUint32(12, 0x666d7420, false); // "fmt "
    dataView.setUint32(16, 16, true);          // PCM格式块大小
    dataView.setUint16(20, 1, true);           // PCM格式代码
    dataView.setUint16(22, channels, true);    // 声道数
    dataView.setUint32(24, sampleRate, true);  // 采样率
    dataView.setUint32(28, sampleRate * channels * bitsPerSample / 8, true); // 字节率
    dataView.setUint16(32, channels * bitsPerSample / 8, true); // 块对齐
    dataView.setUint16(34, bitsPerSample, true); // 位深度

    // data子块
    dataView.setUint32(36, 0x64617461, false); // "data"
    dataView.setUint32(40, dataSize, true);     // PCM数据大小

    return new Uint8Array(buffer);
  }
}

// 转换函数
async function pcmToWav(pcmPath: string, wavPath: string, 
                        sampleRate: number, channels: number, 
                        bitsPerSample: number): Promise<void> {
  try {
    // 读取PCM文件
    const pcmFile = await fs.open(pcmPath, fs.OpenMode.READ_ONLY);
    const pcmStat = await fs.stat(pcmPath);
    const pcmData = new Uint8Array(pcmStat.size);
    await fs.read(pcmFile.fd, pcmData);
    await fs.close(pcmFile);

    // 生成WAV头
    const wavHeader = WavHeader.createHeader(
      sampleRate, channels, bitsPerSample, pcmData.length
    );

    // 合并头和数据
    const wavData = new Uint8Array(wavHeader.length + pcmData.length);
    wavData.set(wavHeader);
    wavData.set(pcmData, wavHeader.length);

    // 写入WAV文件
    const wavFile = await fs.open(wavPath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE);
    await fs.write(wavFile.fd, wavData);
    await fs.close(wavFile);

    console.log('PCM转WAV成功');
  } catch (err) {
    console.error('转换失败:', err);
  }
}

// 使用示例
const pcmPath = 'entry/src/main/resources/rawfile/audio.pcm';
const wavPath = 'entry/src/main/resources/rawfile/audio.wav';
pcmToWav(pcmPath, wavPath, 44100, 2, 16);

4. 注意事项

  • 参数匹配:确保采样率、声道数、位深度与原始PCM数据一致。
  • 文件权限:在module.json5中配置文件读写权限:
    "requestPermissions": [
      {
        "name": "ohos.permission.READ_MEDIA",
        "reason": "读取音频文件"
      },
      {
        "name": "ohos.permission.WRITE_MEDIA",
        "reason": "保存WAV文件"
      }
    ]
    

5. 扩展建议

  • 对于流式PCM数据,可以分段处理并动态生成WAV文件。
  • 若需压缩,可考虑转换为MP3等格式(需使用第三方库)。

通过以上方法,即可在鸿蒙Next中完成PCM到WAV的转换。

回到顶部