在我之前的问题,我设法得到一个工作的.wav文件作为输出。 但是,当我把这个.wav文件放到我的编码器(用其他.wav文件进行testing并且工作正常)的时候,我的编码器在完成之前把错误传回给我。
这是我的输出:
$ ./capture 2 Capture device is plughw:1,0 Finished writing to /tmp/filevXDDX6.wav Starting encode to /tmp/filevXDDX6.flac Wrote 3641 bytes,4096/88200 samples,2/22 frames Wrote 6132 bytes,8192/88200 samples,2/22 frames Wrote 8748 bytes,12288/88200 samples,3/22 frames Wrote 11253 bytes,16384/88200 samples,4/22 frames Wrote 13697 bytes,20480/88200 samples,5/22 frames Wrote 16222 bytes,24576/88200 samples,6/22 frames Wrote 18811 bytes,28672/88200 samples,7/22 frames Wrote 21900 bytes,32768/88200 samples,8/22 frames Wrote 24681 bytes,36864/88200 samples,9/22 frames Wrote 27408 bytes,40960/88200 samples,10/22 frames Wrote 30494 bytes,45056/88200 samples,11/22 frames Wrote 34107 bytes,49152/88200 samples,12/22 frames Wrote 37447 bytes,53248/88200 samples,13/22 frames Wrote 40719 bytes,57344/88200 samples,14/22 frames Wrote 45257 bytes,61440/88200 samples,15/22 frames Wrote 48735 bytes,65536/88200 samples,16/22 frames Wrote 52842 bytes,69632/88200 samples,17/22 frames Wrote 56529 bytes,73728/88200 samples,18/22 frames Wrote 60185 bytes,77824/88200 samples,19/22 frames Wrote 63906 bytes,81920/88200 samples,20/22 frames ERROR: reading from WAVE file Wrote 67687 bytes,86016/88200 samples,21/22 frames Encoding: Failed State: FLAC__STREAM_ENCODER_UNINITIALIZED
我不知道为什么它会提前切断,但我很确定它是如何logging我自己的.wav文件(因为我的编码器可以和其他文件一起工作)。
这是我的代码(对不起,有点长,我尽可能减less):
SuperCollider没有插孔服务器
最简单的方式录制8位带符号单声道16khz声音alsa(在某种程度上,它与脉冲兼容)?
使用ALSA在只播放声卡上捕获播放
具有调制解调器PCM接口的Alsa
除了44.1kHz以外,WAV文件已经混乱了
// Compile with "g++ test.ccp -o test -lasound" // Use the newer ALSA API #define ALSA_PCM_NEW_HW_ParaMS_API #include <alsa/asoundlib.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <stdint.h> struct WaveHeader { char RIFF_marker[4]; uint32_t file_size; char filetype_header[4]; char format_marker[4]; uint32_t data_header_length; uint16_t format_type; uint16_t number_of_channels; uint32_t sample_rate; uint32_t bytes_per_second; uint16_t bytes_per_frame; uint16_t bits_per_sample; }; struct WaveHeader *genericWAVHeader(uint32_t sample_rate,uint16_t bit_depth,uint16_t channels) { struct WaveHeader *hdr; hdr = (WaveHeader*) malloc(sizeof(*hdr)); if (!hdr) return NULL; memcpy(&hdr->RIFF_marker,"RIFF",4); memcpy(&hdr->filetype_header,"WAVE",4); memcpy(&hdr->format_marker,"fmt ",4); hdr->data_header_length = 16; hdr->format_type = 1; hdr->number_of_channels = channels; hdr->sample_rate = sample_rate; hdr->bytes_per_second = sample_rate * channels * bit_depth / 8; hdr->bytes_per_frame = channels * bit_depth / 8; hdr->bits_per_sample = bit_depth; return hdr; } int writeWAVHeader(int fd,struct WaveHeader *hdr) { if (!hdr) return -1; write(fd,&hdr->RIFF_marker,4); write(fd,&hdr->file_size,&hdr->filetype_header,&hdr->format_marker,&hdr->data_header_length,&hdr->format_type,2); write(fd,&hdr->number_of_channels,&hdr->sample_rate,&hdr->bytes_per_second,&hdr->bytes_per_frame,&hdr->bits_per_sample,"data",4); uint32_t data_size = hdr->file_size + 8 - 44; write(fd,&data_size,4); return 0; } int recordWAV(const char *fileName,struct WaveHeader *hdr,uint32_t duration) { int err; int size; snd_pcm_t *handle; snd_pcm_hw_params_t *params; unsigned int sampleRate = hdr->sample_rate; int dir; snd_pcm_uframes_t frames = 32; char *device = (char*) "plughw:1,0"; char *buffer; int filedesc; printf("Capture device is %sn",device); /* Open PCM device for recording (capture). */ err = snd_pcm_open(&handle,device,SND_PCM_STREAM_CAPTURE,0); if (err) { fprintf(stderr,"Unable to open PCM device: %sn",snd_strerror(err)); return err; } /* Allocate a hardware parameters object. */ snd_pcm_hw_params_alloca(¶ms); /* Fill it in with default values. */ snd_pcm_hw_params_any(handle,params); /* ### Set the desired hardware parameters. ### */ /* Interleaved mode */ err = snd_pcm_hw_params_set_access(handle,params,SND_PCM_ACCESS_RW_INTERLEAVED); if (err) { fprintf(stderr,"Error setting interleaved mode: %sn",snd_strerror(err)); snd_pcm_close(handle); return err; } /* Signed 16-bit little-endian format */ if (hdr->bits_per_sample == 16) err = snd_pcm_hw_params_set_format(handle,SND_PCM_FORMAT_S16_LE); else err = snd_pcm_hw_params_set_format(handle,SND_PCM_FORMAT_U8); if (err) { fprintf(stderr,"Error setting format: %sn",snd_strerror(err)); snd_pcm_close(handle); return err; } /* Two channels (stereo) */ err = snd_pcm_hw_params_set_channels(handle,hdr->number_of_channels); if (err) { fprintf(stderr,"Error setting channels: %sn",snd_strerror(err)); snd_pcm_close(handle); return err; } /* 44100 bits/second sampling rate (CD quality) */ sampleRate = hdr->sample_rate; err = snd_pcm_hw_params_set_rate_near(handle,&sampleRate,&dir); if (err) { fprintf(stderr,"Error setting sampling rate (%d): %sn",sampleRate,snd_strerror(err)); snd_pcm_close(handle); return err; } hdr->sample_rate = sampleRate; /* Set period size*/ err = snd_pcm_hw_params_set_period_size_near(handle,&frames,"Error setting period size: %sn",snd_strerror(err)); snd_pcm_close(handle); return err; } /* Write the parameters to the driver */ err = snd_pcm_hw_params(handle,params); if (err < 0) { fprintf(stderr,"Unable to set HW parameters: %sn",snd_strerror(err)); snd_pcm_close(handle); return err; } /* Use a buffer large enough to hold one period */ err = snd_pcm_hw_params_get_period_size(params,"Error retrieving period size: %sn",snd_strerror(err)); snd_pcm_close(handle); return err; } size = frames * hdr->bits_per_sample / 8 * hdr->number_of_channels; /* 2 bytes/sample,2 channels */ buffer = (char *) malloc(size); if (!buffer) { fprintf(stdout,"Buffer error.n"); snd_pcm_close(handle); return -1; } err = snd_pcm_hw_params_get_period_time(params,"Error retrieving period time: %sn",snd_strerror(err)); snd_pcm_close(handle); free(buffer); return err; } uint32_t pcm_data_size = hdr->sample_rate * hdr->bytes_per_frame * duration / 1000; hdr->file_size = pcm_data_size + 44 - 8; filedesc = open(fileName,O_WRONLY | O_CREAT,0644); err = writeWAVHeader(filedesc,hdr); if (err) { fprintf(stderr,"Error writing .wav header."); snd_pcm_close(handle); free(buffer); close(filedesc); return err; } fprintf(stdout,"Channels: %dn",hdr->number_of_channels); for(int i = duration * 1000 / sampleRate; i > 0; i--) { err = snd_pcm_readi(handle,buffer,frames); if (err == -EPIPE) fprintf(stderr,"Overrun occurred: %dn",err); if (err < 0) err = snd_pcm_recover(handle,err,0); // Still an error,need to exit. if (err < 0) { fprintf(stderr,"Error occured while recording: %sn",snd_strerror(err)); snd_pcm_close(handle); free(buffer); close(filedesc); return err; } write(filedesc,size); } close(filedesc); snd_pcm_drain(handle); snd_pcm_close(handle); free(buffer); printf("Finished writing to %sn",fileName); return 0; } int main(int argc,char *argv[]) { if(argc != 2) { fprintf(stderr,"Usage: %s (record duration)n",argv[0]); return -1; } int err; struct WaveHeader *hdr; // Creates a temporary file in /tmp char wavFile[L_tmpnam + 5]; char *tempFilenameStub = tmpnam(NULL); sprintf(wavFile,"%s.wav",tempFilenameStub); hdr = genericWAVHeader(44000,16,2); if (!hdr) { fprintf(stderr,"Error allocating WAV header.n"); return -1; } err = recordWAV(wavFile,hdr,1000 * strtod(argv[1],NULL)); if (err) { fprintf(stderr,"Error recording WAV file: %dn",err); return err; } free(hdr); return 0; }
有什么build议么?
编辑 – 我被告知将我的.wav文件的标题与由arecord生成的标题进行比较。 结果如下:
$ stat -c %s arecord.wav 352844 $ stat -c %s /tmp/filevXDDX6.wav 345004 $ xxd -g1 arecord.wav | head 0000000: 52 49 46 46 44 62 05 00 57 41 56 45 66 6d 74 20 RIFfdb..WAVEfmt 0000010: 10 00 00 00 01 00 02 00 44 ac 00 00 10 b1 02 00 ........D....... 0000020: 04 00 10 00 64 61 74 61 20 62 05 00 08 00 08 00 ....data b...... 0000030: 08 00 08 00 07 00 07 00 fe ff fe ff f7 ff f7 ff ................ 0000040: f6 ff f6 ff ee ff ee ff ee ff ee ff f6 ff f6 ff ................ 0000050: f0 ff f0 ff e7 ff e7 ff ee ff ee ff f4 ff f4 ff ................ 0000060: f4 ff f4 ff f7 ff f7 ff fe ff fe ff fc ff fc ff ................ 0000070: fa ff fa ff f5 ff f5 ff ed ff ed ff ee ff ee ff ................ 0000080: f8 ff f8 ff f4 ff f4 ff ed ff ed ff ee ff ee ff ................ 0000090: f8 ff f8 ff f6 ff f6 ff f0 ff f0 ff ee ff ee ff ................ $ xxd -g1 /tmp/filevXDDX6.wav | head 0000000: 52 49 46 46 44 62 05 00 57 41 56 45 66 6d 74 20 RIFfdb..WAVEfmt 0000010: 10 00 00 00 01 00 02 00 44 ac 00 00 10 b1 02 00 ........D....... 0000020: 04 00 10 00 64 61 74 61 20 62 05 00 71 00 71 00 ....data b..qq 0000030: 6f 00 6f 00 79 00 79 00 75 00 75 00 63 00 63 00 ooyyuucc 0000040: 3e 00 3e 00 1b 00 1b 00 07 00 07 00 fb ff fb ff >.>............. 0000050: 00 00 00 00 0c 00 0c 00 0f 00 0f 00 1c 00 1c 00 ................ 0000060: 30 00 30 00 31 00 31 00 24 00 24 00 1e 00 1e 00 0.0.1.1.$.$..... 0000070: 24 00 24 00 31 00 31 00 2c 00 2c 00 28 00 28 00 $.$.1.1.,.,.(.(. 0000080: 31 00 31 00 3c 00 3c 00 36 00 36 00 31 00 31 00 1.1.<.<.6.6.1.1. 0000090: 39 00 39 00 40 00 40 00 3d 00 3d 00 30 00 30 00 9.9.@.@.=.=.0.0. $ file arecord.wav test.wav: RIFF (little-endian) data,WAVE audio,Microsoft PCM,16 bit,stereo 44100 Hz $ file /tmp/filevXDDX6.wav /tmp/filevXDDX6.wav: RIFF (little-endian) data,stereo 44100 Hz
ALSA&Python – 捕获多个单声道audioinput
Linux中的实时audio分析
如何用ALSA播放短音
枚举捕获ALSA设备并从中捕获
以编程方式在Linux上find可用的声卡
snd_pcm_readi返回实际读取的帧数。 你只能写出很多帧到输出。
duration * 1000 / sampleRate的整数除法可能被舍入。 duration * 1000 / sampleRate * frames可能与您实际想要读取的帧数不完全相同。
你应该重构你的循环来计算总帧数。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。