linux下将pcm文件转换成wav文件——c语言

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/Brouce__Lee/article/details/102545072

前言:我尝试在Linux下将 16k/16b/单通道 的pcm音频转换成wav文件,网上找了很多例子都无法达到效果。于是参考网上的一些资料,写了一个pcm to wav程序,分享给大家。


pcm2wav.c文件

/*
 * @Description:  
 * @version:  V1.0
 * @Company: 
 * @Author: Lipingping
 * @Date: 2019-09-19 11:30:20
 * @LastEditors: Lipingping
 * @LastEditTime: 2019-09-19 11:35:36
 */

#include "wavHeader.h"

long getFileSize(const char *filename)
{
    FILE *fp = fopen(filename, "r");
    if (!fp)
        return -1;
    fseek(fp, 0, SEEK_END);
    long size = ftell(fp);
    fclose(fp);
    return size;
}

void WriteWaveHeader(FILE *fptr, unsigned int num)
{
    WAVE_HEADER WaveHeader;
    FORMAT WaveFormat;
    DATA WaveData;
    /**************RIFF chunk 参数定义*********************/
    WaveHeader.riffid[0] = 'R'; //ChunkID
    WaveHeader.riffid[1] = 'I';
    WaveHeader.riffid[2] = 'F';
    WaveHeader.riffid[3] = 'F';
    WaveHeader.dwSize = num * BYTES_EACH_SAMPLE + 36; //ChunkSize

    WaveHeader.riffType[0] = 'W'; //Format
    WaveHeader.riffType[1] = 'A';
    WaveHeader.riffType[2] = 'V';
    WaveHeader.riffType[3] = 'E';

    /**************fmt chunk 参数定义**********************/
    WaveFormat.fccid[0] = 'f'; //SubChunkID
    WaveFormat.fccid[1] = 'm';
    WaveFormat.fccid[2] = 't';
    WaveFormat.fccid[3] = ' ';

    WaveFormat.dwSize = 16;                                                     //SubChunkSize
    WaveFormat.wFormatTag = 1;                                                  //AudioFormat
    WaveFormat.wChannels = CHANNEL_NUN;                                         //NumChannels
    WaveFormat.dwSamplesPerSec = SAMPLE_RATE;                                   //SampleRate
    WaveFormat.dwAvgBytePerSec = BYTES_EACH_SAMPLE * SAMPLE_RATE * CHANNEL_NUN; //ByteRate
    WaveFormat.wBlockAlign = BYTES_EACH_SAMPLE;                                 //BlockAlign
    WaveFormat.uiBitsPerSample = QUANTIZATION;                                  //BitsPerSample

    /**************Data chunk 参数定义**********************/
    WaveData.fccid[0] = 'd'; //BlockID
    WaveData.fccid[1] = 'a';
    WaveData.fccid[2] = 't';
    WaveData.fccid[3] = 'a';
    WaveData.dwSize = num * BYTES_EACH_SAMPLE; //BlockSize

    fwrite(&WaveHeader, sizeof(WAVE_HEADER), 1, fptr);
    fwrite(&WaveFormat, sizeof(FORMAT), 1, fptr);
    fwrite(&WaveData, sizeof(DATA), 1, fptr);
}

void convertPcm2Wav(const char *inputFile, const char *wavFile)
{
    char buffer[4 * 1024 * 1024] = {};

    FILE *frpcm, *fwwav;
    frpcm = fopen(inputFile, "rb");
    fwwav = fopen(wavFile, "wb");
    if (!frpcm || !fwwav)
    {
        printf("ERROR: failed to fopen.\n");
        exit(1);
    }

    int file_sizes = getFileSize(inputFile);
    int numOfword = fread(buffer, 1, file_sizes, frpcm);

    WriteWaveHeader(fwwav, numOfword);               //向fptr指向的wav文件写入wav标准头文件
    fwrite(buffer, sizeof(short), numOfword, fwwav); //向fptr指向的wav文件写入buffer指向的fcm源文件

    if (frpcm)
    {
        fclose(frpcm);
        frpcm = NULL;
    }

    if (fwwav)
    {
        fclose(fwwav);
        fwwav = NULL;
    }
}

int main(int argc, char const *argv[])
{
    if (argc != 3)
    {
        printf("ERROR: the number of parameters is short.\n  Usage: %s input.pcm output.wav\n", argv[0]);
        exit(1);
    }

    convertPcm2Wav(argv[1], argv[2]);
    return 0;
}

wavHeader.h文件:

/*
 * @Description:  
 * @version:  V1.0
 * @Company: 
 * @Author: Lipingping
 * @Date: 2019-09-19 11:29:07
 * @LastEditors: Lipingping
 * @LastEditTime: 2019-09-19 11:35:24
 */
#ifndef _WAV_H
#define _WAV_H

#include <stdio.h>
#include <stdlib.h>

#define SAMPLE_RATE 16000
#define QUANTIZATION 16
#define BYTES_EACH_SAMPLE 2
#define CHANNEL_NUN 1
#define FORMAT_TAG 1

struct RIFF_CHUNK
{
    char riffid[4];
    unsigned int dwSize;
    char riffType[4];
};
typedef struct RIFF_CHUNK WAVE_HEADER;

struct FORMAT_CHUNK
{
    char fccid[4];
    unsigned int dwSize;
    short wFormatTag;
    short wChannels;
    unsigned int dwSamplesPerSec;
    unsigned int dwAvgBytePerSec;
    short wBlockAlign;
    short uiBitsPerSample;
};
typedef struct FORMAT_CHUNK FORMAT;

struct DATA_CHUNK
{
    char fccid[4];
    unsigned int dwSize;
};

typedef struct DATA_CHUNK DATA;

#endif

猜你喜欢

转载自blog.csdn.net/Brouce__Lee/article/details/102545072