当前位置:首页 > 行业动态 > 正文

如何在C语言中实现Linux环境下的录音功能?

在Linux下录音可以使用命令行工具如 arecord,通过终端输入 arecord -f cd test.wav即可开始录音。

在 Linux 系统中使用 C 语言进行录音,可以通过多种音频库实现,如 ALSA、PortAudio 等,以下是关于在 Linux 下使用 C 语言进行录音的详细内容:

如何在C语言中实现Linux环境下的录音功能?  第1张

使用 ALSA 库进行录音

1、安装 ALSA 库:在 Ubuntu/Debian 系统上,可以使用以下命令安装 ALSA 库和工具:sudo apt-get install alsa-utils libasound2-dev。

2、代码示例:下面是一个使用 ALSA 库进行录音的简单示例代码,该示例以.wav 格式保存录制的音频文件。

   #include <stdio.h>
   #include <stdlib.h>
   #include <alsa/asoundlib.h>
   #define SAMPLE_RATE 44100
   #define NUM_SECONDS 5
   #define OUTPUT_FILE "recorded_audio.wav"
   int main() {
       int err;
       int numSamples = NUM_SECONDS * SAMPLE_RATE;
       short *recordedSamples;
       recordedSamples = (short *)malloc(sizeof(short) * numSamples);
       if (recordedSamples == NULL) {
           printf("Failed to allocate memory.
");
           return 1;
       }
       snd_pcm_t *handle;
       snd_pcm_hw_params_t *params;
       err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0);
       if (err < 0) {
           printf("Failed to open PCM device: %s
", snd_strerror(err));
           return 1;
       }
       snd_pcm_hw_params_alloca(&params);
       err = snd_pcm_hw_params_any(handle, params);
       if (err < 0) {
           printf("Failed to initialize PCM device parameters: %s
", snd_strerror(err));
           return 1;
       }
       err = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
       if (err < 0) {
           printf("Failed to set PCM device access type: %s
", snd_strerror(err));
           return 1;
       }
       err = snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
       if (err < 0) {
           printf("Failed to set PCM device sample format: %s
", snd_strerror(err));
           return 1;
       }
       err = snd_pcm_hw_params_set_rate_near(handle, params, &SAMPLE_RATE, 0);
       if (err < 0) {
           printf("Failed to set PCM device sample rate: %s
", snd_strerror(err));
           return 1;
       }
       err = snd_pcm_hw_params_set_channels(handle, params, 1);
       if (err < 0) {
           printf("Failed to set PCM device channel count: %s
", snd_strerror(err));
           return 1;
       }
       err = snd_pcm_hw_params(handle, params);
       if (err < 0) {
           printf("Failed to set PCM device parameters: %s
", snd_strerror(err));
           return 1;
       }
       printf("Recording started. Press Ctrl+C to stop recording.
");
       while (numSamples > 0) {
           err = snd_pcm_readi(handle, recordedSamples, numSamples);
           if (err == -EPIPE) {
               printf("Overrun occurred.
");
               snd_pcm_prepare(handle);
           } else if (err < 0) {
               printf("Failed to read from PCM device: %s
", snd_strerror(err));
               return 1;
           } else {
               numSamples -= err;
               recordedSamples += err * snd_pcm_hw_params_get_channels(params);
           }
       }
       err = snd_pcm_close(handle);
       if (err < 0) {
           printf("Failed to close PCM device: %s
", snd_strerror(err));
           return 1;
       }
       FILE *file = fopen(OUTPUT_FILE, "wb");
       if (file == NULL) {
           printf("Failed to open output file.
");
           return 1;
       }
       fwrite(recordedSamples, sizeof(short), NUM_SECONDS * SAMPLE_RATE, file);
       fclose(file);
       free(recordedSamples);
       printf("Recording finished. Saved as %s
", OUTPUT_FILE);
       return 0;
   }

3、编译运行:将上述代码保存为record.c,然后使用以下命令进行编译和运行:gcc record.c -o record -lasound,运行./record 即可开始录音,录制的音频文件将保存为recorded_audio.wav。

使用 PortAudio 库进行录音

1、安装 PortAudio 库:在 Ubuntu/Debian 系统上,可以使用以下命令安装 PortAudio 库:sudo apt-get install portaudio19-dev。

2、代码示例:下面是一个使用 PortAudio 库进行录音的简单示例代码:

   #include <stdio.h>
   #include <stdlib.h>
   #include "portaudio.h"
   #define NUM_SECONDS 5
   #define SAMPLE_RATE 44100
   #define FRAMES_PER_BUFFER 256
   typedef struct {
       float left_phase;
       float right_phase;
   } paTestData;
   static int patestCallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void *userData) {
       paTestData *data = (paTestData*)userData;
       float *out = (float*)outputBuffer;
       unsigned long i;
       (void) inputBuffer;  // Prevent unused variable warning.
       (void) timeInfo;    // Prevent unused variable warning.
       (void) statusFlags; // Prevent unused variable warning.
       for (i = 0; i < framesPerBuffer; i++) {
           *out++ = data->left_phase;  /* mono output */
           data->left_phase += 0.01f;
           if (data->left_phase >= 1.0f) data->left_phase -= 1.0f;
       }
       return 0;
   }
   int main(void) {
       PaError err;
       PaStreamParameters inputParameters;
       PaStream *stream;
       paTestData data;
       data.left_phase = data.right_phase = 0.0;
       err = Pa_Initialize();
       if (err != paNoError) goto error;
       inputParameters.device = Pa_GetDefaultInputDevice();  // default input device
       if (inputParameters.device == paNoDevice) {
           fprintf(stderr, "Error: No default input device.
");
           goto done;
       }
       inputParameters.channelCount = 2;                    // stereo input
       inputParameters.sampleFormat = paFloat32;            // 32 bit floating point input
       inputParameters.suggestedLatency = Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency;
       inputParameters.hostApiSpecificStreamInfo = NULL;
       err = Pa_OpenStream(&stream, &inputParameters, NULL, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, NULL, NULL);
       if (err != paNoError) goto done;
       err = Pa_StartStream(stream);
       if (err != paNoError) goto done;
       printf("Recording started. Press Ctrl+C to stop recording.
");
       while (1) {
           err = Pa_Sleep(1000);  // Record for 1 second.
           if (err != paNoError) goto done;
       }
       done:
       Pa_StopStream(stream);
       if (err != paNoError) goto error;
       Pa_CloseStream(stream);
       Pa_Terminate();
       printf("Recording finished.
");
       return err;
   error:
       Pa_Terminate();
       fprintf(stderr, "An error occured while using the portaudio stream
");
       fprintf(stderr, "Error number: %d
", err);
       fprintf(stderr, "Error message: %s
", Pa_GetErrorText(err));
       return err;
   }

3、编译运行:将上述代码保存为record_portaudio.c,然后使用以下命令进行编译和运行:gcc record_portaudio.c -o record_portaudio -lportaudio -lpthread -lm,运行./record_portaudio 即可开始录音。

常见问题及解答:

1、录音过程中出现杂音:可能是输入设备音量过大导致,可以在系统设置的声音输入设备中调整音量,根据系统提示的当时音量值调整一个合适的输入音量,录音完成后可以用 Audacity 降噪。

2、无法找到默认音频输入设备:在使用 PortAudio 或 ALSA 时,如果无法找到默认音频输入设备,可以手动指定设备名称或 ID,对于 ALSA,可以通过aplay -l 命令查看可用的音频设备;对于 PortAudio,可以使用Pa_GetDeviceInfo 函数获取设备信息并选择合适的设备。

0