Сжатие по u-law возвращает неверный файл c ++ - PullRequest
0 голосов
/ 09 марта 2020

Я пытаюсь применить алгоритм u-law к файлу wav file.wav, а затем создать новый файл file2.wav. file.wav имеет 16 бит / семпл, и я хочу получить file2.wav, который имеет 8 бит / семпл.

Это мой код:

#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- закон алгоритма из здесь (2.1. алгоритм сжатия (кодирования) µ-закона)

Я что-то не так делаю? Потому что я получаю поврежденный файл.

value[i]

1 Ответ

0 голосов
/ 09 марта 2020

Заголовок никогда не записывается в файл результатов, поэтому первая часть данных будет интерпретирована как заголовок, и это будет неправильно. В файле видно, что он начинается не с RIFFþR�WAVEfmt или с чего-то достаточно похожего.

Данные, записываемые в файл результатов, value, исходные данные считываются из входного файла, а не µ закодированные данные (которые только cout 'редактируются и не сохраняются).

l oop, который читает выборки, считывает некоторые неправильные выборки, потому что вычисление samples_count возвращает текущую позицию обратно в начале, где заголовок.

...