【问题标题】:u-law compression returns invalid file c++u-law 压缩返回无效文件 c++
【发布时间】:2020-03-08 21:34:58
【问题描述】:

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

这是我的代码:

#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;
}

我取自here的u-law算法(2.1. µ-Law Compression (Encoding) Algorithm)

我做错了吗?因为我得到了一个损坏的文件。

【问题讨论】:

    标签: c++ compression wav mu-law


    【解决方案1】:

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

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

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

    【讨论】:

    • 我明白了,我如何获取标头的大小以便我可以执行samples_count-header_size 之类的操作并从该值开始for 循环?
    • sizeof(wavHeader) 可以吗?
    • @Mr.Wizard 你可以fseeksizeof(wavHeader),还有其他各种解决方案.. 例如你可以使用在标题中找到的大小,而不是使用fseek/@ 987654331@东西找长度,反正看起来更简单
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-04
    • 2012-01-23
    • 2020-01-09
    • 1970-01-01
    • 2013-07-29
    • 2012-09-05
    • 1970-01-01
    相关资源
    最近更新 更多