美文网首页
wav音频通道数修改工具 C语言实现

wav音频通道数修改工具 C语言实现

作者: VellBibi | 来源:发表于2023-11-03 12:02 被阅读0次

    前言

    最近研究了下wav格式,为了巩固下对格式的认识,写了个小工具来修改音频通道数,原理很简单,看两张图就大概懂了

    wav格式

    信息头结构


    数据排列方式


    废话不多说,直接上代码

    转换代码

    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <string.h>
    #include <signal.h>
    #include <endian.h>
    #include <unistd.h>
    
    #define ID_RIFF 0x46464952
    #define ID_WAVE 0x45564157
    #define ID_FMT  0x20746d66
    #define ID_DATA 0x61746164
    
    struct wav_header {
        uint32_t riff_id;
        uint32_t riff_sz;
        uint32_t riff_fmt;
        uint32_t fmt_id;
        uint32_t fmt_sz;
        uint16_t audio_format;
        uint16_t num_channels;
        uint32_t sample_rate;
        uint32_t byte_rate;
        uint16_t block_align;
        uint16_t bits_per_sample;
        uint32_t data_id;
        uint32_t data_sz;
    };
    
    int main(int argc, char **argv) {
        FILE *file;
        FILE *out;
        struct wav_header in_header;
        unsigned int channels = 2;
        char *filename;
        char *out_filename;
        int more_chunks = 1;
    
        if (argc < 3) {
            fprintf(stderr, "Usage: %s in.wav out.wav [-c channels] \n", argv[0]);
            return 1;
        }
    
        filename = argv[1];
        file = fopen(filename, "rb");
        if (!file) {
            fprintf(stderr, "Unable to open file '%s'\n", filename);
            return 1;
        }
        out_filename = argv[2];
        out = fopen(out_filename, "wb");
        if (!out) {
            fprintf(stderr, "Unable to open file '%s'\n", out_filename);
            return 1;
        }
    
        fread(&in_header, sizeof(in_header), 1, file);
        if ((in_header.riff_id != ID_RIFF) ||
            (in_header.riff_fmt != ID_WAVE)) {
            fprintf(stderr, "Error: '%s' is not a riff/wave file\n", filename);
            fclose(file);
            return 1;
        }
    
        /* parse command line arguments */
        argv += 3;
        while (*argv) {
            if (strcmp(*argv, "-c") == 0) {
                argv++;
                if (*argv)
                    channels = atoi(*argv);
            }
            if (*argv)
                argv++;
        }
    
        struct wav_header out_header;
        memcpy(&out_header, &in_header, sizeof(out_header));
        out_header.num_channels = channels;
        out_header.block_align = out_header.num_channels * (out_header.bits_per_sample / 8);
        out_header.data_sz = out_header.block_align * (in_header.data_sz / in_header.block_align);
        out_header.riff_sz = out_header.data_sz + sizeof(out_header) - 8;
        fwrite(&out_header, sizeof(struct wav_header), 1, out);
    
        fseek(file, sizeof(struct wav_header), SEEK_SET);
        fseek(out, sizeof(struct wav_header), SEEK_SET);
        char *buffer = malloc(in_header.block_align);
        for (int i = 0; i < in_header.data_sz; i += in_header.block_align) {
            if (fread(buffer, 1, in_header.block_align, file) != in_header.block_align) {
                fprintf(stderr, "Error read file\n");
                break;
            }
            if (in_header.num_channels > out_header.num_channels) {
                // remove channel
                if (fwrite(buffer, 1, out_header.block_align, out) != out_header.block_align) {
                    fprintf(stderr, "Error write file\n");
                    break;
                }
            } else if (in_header.num_channels < out_header.num_channels) {
                // add channel
                if (fwrite(buffer, 1, in_header.block_align, out) != in_header.block_align) {
                    fprintf(stderr, "Error write file\n");
                    break;
                }
                for (int j = 0; j < out_header.num_channels - in_header.num_channels; j++) {
                    // add channel with first channel
                    if (fwrite(buffer, 1, in_header.block_align / in_header.num_channels, out) !=
                        in_header.block_align / in_header.num_channels) {
                        fprintf(stderr, "Error write file\n");
                        break;
                    }
                }
            }
        }
        fclose(file);
        fclose(out);
    
        return 0;
    }
    

    相关文章

      网友评论

          本文标题:wav音频通道数修改工具 C语言实现

          本文链接:https://www.haomeiwen.com/subject/fvroidtx.html