gpt4 book ai didi

c++ - 将原始 PCM 转换为 FLAC?

转载 作者:太空狗 更新时间:2023-10-29 20:42:57 34 4
gpt4 key购买 nike

编辑:我已经更新了下面的代码以类似于我取得的进展。我正在尝试自己编写 .wav header 。截至目前,代码无法正常工作,音频未正确写入文件。该代码不包含任何将其转换为 .flac 文件的尝试。


我正在使用 Raspberry Pi ( Debian Linux ) 通过 ALSA library 录制音频.录音工作正常,但我需要将输入音频编码为 FLAC 编解码器。

这是我迷路的地方。我花了相当多的时间试图弄清楚如何将这些原始数据转换成 FLAC ,但我一直在想出如何将 .wav 文件转换为 .flac 文件的示例。

这是我使用 ALSA 录制音频的当前(更新)代码(它可能有点粗糙,我仍在使用 C++):

// Use the newer ALSA API
#define ALSA_PCM_NEW_HW_PARAMS_API

#include <alsa/asoundlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct Riff
{
char chunkId[4]; // "RIFF" (assuming char is 8 bits)
int chunkSize; // (assuming int is 32 bits)
char format[4]; // "WAVE"
};

struct Format
{
char chunkId[4]; // "fmt "
int chunkSize;
short format; // assuming short is 16 bits
short numChannels;
int sampleRate;
int byteRate;
short align;
short bitsPerSample;
};

struct Data
{
char chunkId[4]; // "data"
int chunkSize; // length of data
char* data;
};

struct Wave // Actual structure of a PCM WAVE file
{
Riff riffHeader;
Format formatHeader;
Data dataHeader;
};

int main(int argc, char *argv[])
{
void saveWaveFile(struct Wave *waveFile);

long loops;
int rc;
int size;
snd_pcm_t *handle;
snd_pcm_hw_params_t *params;
unsigned int sampleRate = 44100;
int dir;
snd_pcm_uframes_t frames;
char *buffer;
char *device = (char*) "plughw:1,0";
//char *device = (char*) "default";

printf("Capture device is %s\n", device);
/* Open PCM device for recording (capture). */
rc = snd_pcm_open(&handle, device, SND_PCM_STREAM_CAPTURE, 0);
if (rc < 0)
{
fprintf(stderr, "Unable to open PCM device: %s\n", snd_strerror(rc));
exit(1);
}

/* Allocate a hardware parameters object. */
snd_pcm_hw_params_alloca(&params);

/* Fill it in with default values. */
snd_pcm_hw_params_any(handle, params);

/* Set the desired hardware parameters. */

/* Interleaved mode */
snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);

/* Signed 16-bit little-endian format */
snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);

/* Two channels (stereo) */
snd_pcm_hw_params_set_channels(handle, params, 2);

/* 44100 bits/second sampling rate (CD quality) */
snd_pcm_hw_params_set_rate_near(handle, params, &sampleRate, &dir);

/* Set period size to 32 frames. */
frames = 32;
snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);

/* Write the parameters to the driver */
rc = snd_pcm_hw_params(handle, params);
if (rc < 0)
{
fprintf(stderr, "Unable to set HW parameters: %s\n", snd_strerror(rc));
exit(1);
}

/* Use a buffer large enough to hold one period */
snd_pcm_hw_params_get_period_size(params, &frames, &dir);
size = frames * 4; /* 2 bytes/sample, 2 channels */
buffer = (char *) malloc(size);

/* We want to loop for 5 seconds */
snd_pcm_hw_params_get_period_time(params, &sampleRate, &dir);
loops = 5000000 / sampleRate;

while (loops > 0)
{
loops--;
rc = snd_pcm_readi(handle, buffer, frames);
if (rc == -EPIPE)
{
/* EPIPE means overrun */
fprintf(stderr, "Overrun occurred.\n");
snd_pcm_prepare(handle);
} else if (rc < 0)
{
fprintf(stderr, "Error from read: %s\n", snd_strerror(rc));
} else if (rc != (int)frames)
{
fprintf(stderr, "Short read, read %d frames.\n", rc);
}
if (rc != size) fprintf(stderr, "Short write: wrote %d bytes.\n", rc);
}

Wave wave;

strcpy(wave.riffHeader.chunkId, "RIFF");
wave.riffHeader.chunkSize = 36 + size;
strcpy(wave.riffHeader.format, "WAVE");

strcpy(wave.formatHeader.chunkId, "fmt");
wave.formatHeader.chunkSize = 16;
wave.formatHeader.format = 1; // PCM, other value indicates compression
wave.formatHeader.numChannels = 2; // Stereo
wave.formatHeader.sampleRate = sampleRate;
wave.formatHeader.byteRate = sampleRate * 2 * 2;
wave.formatHeader.align = 2 * 2;
wave.formatHeader.bitsPerSample = 16;

strcpy(wave.dataHeader.chunkId, "data");
wave.dataHeader.chunkSize = size;
wave.dataHeader.data = buffer;

saveWaveFile(&wave);

snd_pcm_drain(handle);
snd_pcm_close(handle);
free(buffer);

return 0;
}

void saveWaveFile(struct Wave *waveFile)
{
FILE *file = fopen("test.wav", "wb");
size_t written;

if (file == NULL)
{
fprintf(stderr, "Cannot open file for writing.\n");
exit(1);
}

written = fwrite(waveFile, sizeof waveFile[0], 1, file);
fclose(file);

if (written < 1);
{
fprintf(stderr, "Writing to file failed, error %d.\n", written);
exit(1);
}
}

我如何将 PCM 数据转换为 FLAC 并将其保存到磁盘以备后用?我已经下载了 libflac-dev,只需要一个示例即可。


我现在的做法是:

./capture > test.raw     // or   ./capture > test.flac

它应该是这样的(程序为我做了一切):

./capture

最佳答案

如果我理解FLAC::Encoder::File文档,你可以做类似的事情

#include <FLAC++/encoder.h>

FLAC::Encoder::File encoder;
encoder.init("outfile.flac");
encoder.process(buffer, samples);
encoder.finish();

其中 buffer 是 32 位整数指针的数组(大小为 samples)。

不幸的是,我对音频编码几乎一无所知,所以我不能说任何其他选择。祝你好运!

关于c++ - 将原始 PCM 转换为 FLAC?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17139974/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com