转换原始的PCM后手

转换原始的PCM后手

本文介绍了转换原始的PCM后手?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

编辑:我已经更新了下面的code到像我所取得的进展。我试图写的 .WAV 头自己。在code不截至目前正常工作,音频不被写入文件正确。在code不含任何企图将其转换为 .FLAC 文件呢。


我使用的是树莓派()来记录与的。录音工作正常,但我需要带code输入音频成FLAC codeC。

这是我迷路。我花了相当多的时间试图找出如何将这个原始数据转换成,但我一直想出如何转换 .WAV 文件的示例为 .FLAC 文件。

下面是电流(更新)code我有记录与ALSA音频(它可能是一个有点粗糙,我还是拿起C ++):

  //使用较新的ALSA API
#定义ALSA_PCM_NEW_HW_PARAMS_API#包括LT&; ALSA / asoundlib.h>
#包括LT&;&stdio.h中GT;
#包括LT&;&stdlib.h中GT;
#包括LT&;&string.h中GT;结构的Riff
{
  炭chunkId [4]; //RIFF(假设char是8位)
  INT CHUNKSIZE; //(假设int是32位)
  char格式[4]; //WAVE
};结构形式
{
  炭chunkId [4]; //FMT
  INT CHUNKSIZE;
  短格式; //假设短为16位
  短numChannels;
  INT采样率;
  INT byteRate;
  短对齐;
  短bitsPerSample;
};数据结构
{
  炭chunkId [4]; //数据
  INT CHUNKSIZE; //数据的长度
  字符*的数据;
};结构波//一个PCM WAVE文件的实际结构
{
  即兴riffHeader;
  格式formatHeader;
  数据dataHeader;
};INT主(INT ARGC,CHAR *的argv [])
{
        无效saveWaveFile(结构波* waveFile);        长循环;
        INT RC;
        INT大小;
        snd_pcm_t *手柄;
        snd_pcm_hw_params_t * PARAMS;
        unsigned int类型采样率= 44100;
        INT目录;
        snd_pcm_uframes_t帧;
        字符*缓冲区;
        字符*设备=(字符*)plughw:1,0;
        //字符*设备=(字符*)默认;        的printf(捕捉设备为%s \\ n,设备);
        / *记录(捕捉)打开PCM设备。 * /
        RC = snd_pcm_open(安培;手柄,装置SND_PCM_STREAM_CAPTURE,0);
        如果(RC℃,)
        {
                fprintf中(标准错误,无法打开PCM设备:%S \\ n,snd_strerror(RC));
                出口(1);
        }        / *分配一个硬件参数对象。 * /
        snd_pcm_hw_params_alloca(安培; PARAMS);        / *使用默认值填充进去。 * /
        snd_pcm_hw_params_any(手柄,则params);        / *设置所需的硬件参数。 * /        / *交互模式* /
        snd_pcm_hw_params_set_access(手柄,则params,SND_PCM_ACCESS_RW_INTERLEAVED);        / *符号16位小尾数格式* /
        snd_pcm_hw_params_set_format(手柄,则params,SND_PCM_FORMAT_S16_LE);        / *两个通道(立体声)* /
        snd_pcm_hw_params_set_channels(手柄,参数,2);        / * 44100比特/秒的采样率(CD质量)* /
        snd_pcm_hw_params_set_rate_near(手柄,参数,可以和放大器;采样率,和放大器; DIR);        / *设置期间大小32帧。 * /
        帧= 32;
        snd_pcm_hw_params_set_period_size_near(手柄,参数,可以和放大器;帧,&安培; DIR);        / *写入参数向驾驶员* /
        RC = snd_pcm_hw_params(手柄,则params);
        如果(RC℃,)
        {
                fprintf中(标准错误,无法设置硬件参数:%S \\ n,snd_strerror(RC));
                出口(1);
        }        / *使用足够大的缓冲区来保存一个周期* /
        snd_pcm_hw_params_get_period_size(参数,可以和放大器;帧,&安培; DIR);
        大小=帧* 4; / * 2字节/样品,2通道* /
        缓冲=(字符*)malloc的(大小);        / *我们要循环5秒* /
        snd_pcm_hw_params_get_period_time(参数,可以和放大器;采样率,和放大器; DIR);
        循环= 500万支/采样率;        而(循环大于0)
        {
                loops--;
                RC = snd_pcm_readi(手柄,缓冲器,帧);
                如果(RC == -EPIPE)
                {
                        / * EPIPE意味着溢出* /
                        fprintf中(标准错误,超限发生\\ n);
                        snd_pcm_ prepare(手柄);
                }否则如果(RC℃,)
                {
                        fprintf中(标准错误,从读取错误:%s \\ n,snd_strerror(RC));
                }否则如果(RC!=(int)的帧)
                {
                        fprintf中(标准错误,短读,读%d个帧\\ n,RC);
                }
                如果(!RC =大小)fprintf中(标准错误,短写:写%d字节\\ n,RC);
        }        浪高过一浪;        的strcpy(wave.riffHeader.chunkIdRIFF);
        wave.riffHeader.chunkSize = 36 +大小;
        的strcpy(wave.riffHeader.format,WAVE);        的strcpy(wave.formatHeader.chunkIdFMT);
        wave.formatHeader.chunkSize = 16;
        wave.formatHeader.format = 1; // PCM,其他值表示COM pression
        wave.formatHeader.numChannels = 2; //立体声
        wave.formatHeader.sampleRate =采样率;
        wave.formatHeader.byteRate =采样率* 2 * 2;
        wave.formatHeader.align = 2 * 2;
        wave.formatHeader.bitsPerSample = 16;        的strcpy(wave.dataHeader.chunkId,数据);
        wave.dataHeader.chunkSize =大小;
        wave.dataHeader.data =缓冲;        saveWaveFile(安培;波);        snd_pcm_drain(手柄);
        snd_pcm_close(手柄);
        免费(缓冲);        返回0;
}无效saveWaveFile(结构波* waveFile)
{
        FILE *文件=的fopen(test.wav,世行);
        size_t型写的;        如果(文件== NULL)
        {
                fprintf中(标准错误,无法打开文件进行写入\\ n);
                出口(1);
        }        书面= fwrite的(waveFile,sizeof的waveFile [0],1,文件);
        FCLOSE(文件);        如果(书面< 1);
        {
                fprintf中(标准错误,写文件失败,错误%d个\\ n,写的);
                出口(1);
        }
}

我怎么会去PCM数据转换成FLAC,并将其保存到磁盘供以后使用?我已经下载 libflac-dev的已经和只需要一个例子来熄灭的。


我现在正在做它的方式:

  ./捕获> test.raw //或./capture> test.flac

应该是的方式(程序做的一切对我来说):

  ./捕获


解决方案

请参考下面的code:

<一个href=\"https://git.xiph.org/?p=flac.git;a=blob;f=examples/c/en$c$c/file/main.c;h=dab772606898f5ccd569d64ce1d6ed6e4e138537;hb=HEAD\"相对=nofollow> FLAC恩codeR测试code

这例子是使用wav文件作为输入,然后连接codeS入FLAC。

据我了解,有一个b / w的WAV文件和你的RAW数据并不是很大,我觉得你可以修改此code直接读取缓冲,并将其转换。你已经拥有的所有相关信息(频道/比特率等),所以它不应该是太大的问题,除去WAV头读取code。

EDIT: I've updated the code below to resemble the progress I have made. I'm trying to write the .wav header myself. The code does not work properly as of now, the audio is not being written to the file properly. The code does not contain any attempts to convert it to a .flac file yet.


I am using a Raspberry Pi (Debian Linux) to record audio with the ALSA library. The recording works fine, but I need to encode the input audio into the FLAC codec.

This is where I get lost. I have spent a considerable amount of time trying to figure out how to convert this raw data into FLAC, but I keep coming up with examples of how to convert .wav files into .flac files.

Here is the current (updated) code I have for recording audio with ALSA (it may be a bit rough, I'm still picking up 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);
        }
}

How would I go about converting the PCM data into the FLAC and save it to disk for later use? I have downloaded libflac-dev already and just need an example to go off of.


The way I am doing it right now:

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

The way it should be (program does everything for me):

./capture
解决方案

Please refer to the below code :

FLAC Encoder Test Code

This example is using a wav file as an input and then encodes it into FLAC.

As I understand, there is no major difference b/w WAV file and your RAW data, I think you can modify this code to directly read the "buffer" and convert it. You already have all the related information (Channel/Bitrate etc) so it should not be much of a problem to remove the WAV header reading code.

这篇关于转换原始的PCM后手?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-14 00:52