0

我正在尝试将 u-law 算法应用于 wav 文件file.wav,然后创建一个新文件file2.wavfile.wav有 16 位/样本,我想获得一个file2.wav8 位/样本。

这是我的代码:

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <iostream>
#include <string>
#include <fstream>

using namespace std;
using std::string;
using std::fstream;

typedef struct  WAV_HEADER {
    char                RIFF[4];
    unsigned long       ChunkSize;
    char                WAVE[4];
    char                fmt[4];
    unsigned long       Subchunk1Size;
    unsigned short      AudioFormat;
    unsigned short      NumOfChan;
    unsigned long       SamplesPerSec;
    unsigned long       bytesPerSec;
    unsigned short      blockAlign;
    unsigned short      bitsPerSample;
    char                Subchunk2ID[4];
    unsigned long       Subchunk2Size;

} wav_hdr;

int headerSize = 0;
string path = "file.wav";
wav_hdr wavHeader;

FILE* openFile() {
    const char* filePath;
    FILE *wavFile;

    headerSize = sizeof(wav_hdr);
    filePath = path.c_str();
    wavFile = fopen(filePath, "rb");

    if (wavFile == NULL) {
        printf("Error\n");
    }

    fread(&wavHeader, headerSize, 1, wavFile);

    return wavFile;
}

int8_t MuLaw_Encode(int16_t number)
{
    const uint16_t MULAW_MAX = 0x1FFF;
    const uint16_t MULAW_BIAS = 33;
    uint16_t mask = 0x1000;
    uint8_t sign = 0;
    uint8_t position = 12;
    uint8_t lsb = 0;
    if (number < 0)
    {
        number = -number;
        sign = 0x80;
    }
    number += MULAW_BIAS;
    if (number > MULAW_MAX)
    {
        number = MULAW_MAX;
    }
    for (; ((number & mask) != mask && position >= 5); mask >>= 1, position--)
        ;
    lsb = (number >> (position - 4)) & 0x0f;
    return (~(sign | ((position - 5) << 4) | lsb));
}

int fileSize(FILE *file) {
    int fileSize = 0;

    fseek(file, 0, SEEK_END);
    fileSize = ftell(file);
    fseek(file, 0, SEEK_SET);

    return fileSize;
}

double bitsPerSample() {
    double bitsPerE;

    bitsPerE = wavHeader.bitsPerSample;
    return bitsPerE;
}

int main() {
    FILE *wavFile;
    wavFile = openFile();
    FILE* fptr2;
    fptr2 = fopen("file2.wav", "wb");

    int samples_count = fileSize(wavFile) / bitsPerSample();
    short int *value = new short int[samples_count];

    for (int16_t i = 0; i < samples_count; i++)
    {
        fread(&value[i], samples_count, 1, wavFile);
        cout << value[i] << " "; // the output is in the attached picture
        MuLaw_Encode(value[i]);
    }
        fwrite(value, sizeof(char), samples_count, fptr2);

    return 0;
}

我从这里 取了 u-law 算法(2.1. µ-Law Compression (Encoding) Algorithm)

难道我做错了什么?因为我获得了一个损坏的文件。

值[i]

4

1 回答 1

0

没有头文件被写入结果文件,因此数据的第一部分将被解释为头文件,这将是错误的。您可以在文件中看到它不是以开头RIFFþR�WAVEfmt或类似的东西开头。

写入结果文件的数据是value从输入文件读取的原始数据,而不是 µ-law 编码数据(仅被cout'ed 而不保存)。

读取样本的循环读取了一些错误的样本,因为计算samples_count将当前位置放回到开头,即标题所在的位置。

于 2020-03-08T21:51:55.970 回答