我正在尝试开始使用 PortAudio。我能够毫无问题地构建捆绑的示例文件“paex_sine.c”。这是左声道上的正弦波和右声道上不同频率的正弦波。这可以正常工作,没有错误。
我的设置是一台运行 Puppy Linux Slacko 5.5 的 32 位 PC。它有一个带有 EMU10k1x 芯片的 SoundBlaster SB0200。Alsa 库是 v1.0.26,驱动程序是 v1.0.24。我已经使用这个命令测试了所有 5.1 通道:
% 扬声器测试 -Dplug:surround51 -c6
该测试在 6 个通道中的每一个上都能正常播放声音,尽管它确实抱怨管道损坏。这可能是因为测试程序中所有 6 个通道的缓冲区不够大。
我遇到的问题是,当我修改“paex_sine.c”以在 6 个通道而不是 2 个通道上运行时,它只会通过右前和左前通道播放声音。没有报告错误,并且 2 个通道听起来应该。我听说在某些情况下必须取消静音。在 AlsaMixer 和 Puppy 的“Retrovol”(反映 AlsaMixer)中,我已将 Master、PCM 和 Surround 设置为最大音量,未静音。PortAudio 中是否有我也必须取消静音的混音器?我可以在正确运行扬声器测试和运行修改后的 paex_sine 示例和只听到 2 个通道之间来回切换。这是我修改过的 paex_sine.c:
/** @file paex_sine.c @ingroup examples_src @brief 播放几秒钟的正弦波。 @作者罗斯·本西纳 <rossb@audiomulch.com> @作者菲尔伯克 <philburk@softsynth.com> */ /* * $Id:paex_sine.c 1752 2011-09-08 03:21:55Z 菲尔伯克 $ * * 该程序使用 PortAudio 便携式音频库。 * 欲了解更多信息,请参阅:http://www.portaudio.com/ * 版权所有 (c) 1999-2000 Ross Bencina 和 Phil Burk * * 特此免费授予任何获得许可的人 * 该软件和相关文档文件的副本 *(“软件”),不受限制地处理软件, * 包括但不限于使用、复制、修改、合并、 * 发布、分发、再许可和/或出售软件的副本, * 并允许向其提供软件的人这样做, * 须符合以下条件: * * 以上版权声明和本许可声明为 * 包含在软件的所有副本或大部分内容中。 * * 软件按“原样”提供,不提供任何形式的保证, * 明示或暗示,包括但不限于 * 适销性、特定用途的适用性和非侵权性。 * 在任何情况下,作者或版权所有者均不承担任何责任 * 任何索赔、损害赔偿或其他责任,无论是在诉讼中 * 合同、侵权或其他原因,由、不相关或相关 * 与软件或软件中的使用或其他交易有关。 */ /* * 以上文字构成整个 PortAudio 许可证;然而, * PortAudio 社区还提出以下非约束性请求: * * 任何希望分发对软件的修改的人 * 要求将修改发送给原始开发人员,以便 * 它们可以合并到规范版本中。也是 * 要求将这些不具约束力的请求与 * 上面的许可证。 */ #include <stdio.h> #include <math.h> #include “portaudio.h” #define NUM_SECONDS (30) #define SAMPLE_RATE (44100) #define FRAMES_PER_BUFFER (192)//(64) #ifndef M_PI #define M_PI (3.14159265) #万一 #define TABLE_SIZE (200) 类型定义结构 { 浮动正弦[TABLE_SIZE]; 诠释左相; int right_phase; int left2_phase; 诠释 right2_phase; int left3_phase; int right3_phase; 字符消息[20]; } 测试数据; /* 当需要音频时,PortAudio 引擎将调用此例程。 ** 它可能在某些机器上以中断级别调用,所以不要做任何事情 ** 这可能会像调用 malloc() 或 free() 一样搞砸系统。 */ 静态 int patestCallback( const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, 常量 PaStreamCallbackTimeInfo* 时间信息, PaStreamCallbackFlags statusFlags, 无效*用户数据) { paTestData *data = (paTestData*)userData; 浮动 *out = (float*)outputBuffer; 无符号长 i; (无效)时间信息;/* 防止未使用的变量警告。*/ (void) 状态标志; (void) 输入缓冲区; for(i=0;i<framesPerBuffer;i++) { *out++ = 数据->正弦[数据->left_phase]; /* 剩下 */ *out++ = 数据->正弦[数据->right_phase]; /* 正确的 */ *out++ = 数据->正弦[数据->left2_phase]; /* 剩下 */ *out++ = 数据->正弦[数据->right2_phase]; /* 正确的 */ *out++ = 数据->正弦[数据->left3_phase]; /* 剩下 */ *out++ = 数据->正弦[数据->right3_phase]; /* 正确的 */ 数据->left_phase += 1; if( 数据->left_phase >= TABLE_SIZE ) 数据->left_phase -= TABLE_SIZE; 数据->right_phase += 3; /* 更高的音高,这样我们就可以区分左右。*/ if( 数据->right_phase >= TABLE_SIZE ) 数据->right_phase -= TABLE_SIZE; 数据->left2_phase += 5; if( 数据->left2_phase >= TABLE_SIZE ) 数据->left2_phase -= TABLE_SIZE; 数据->right2_phase += 7;/* 更高的音高,这样我们就可以区分左右。*/ if( 数据->right2_phase >= TABLE_SIZE ) 数据->right2_phase -= TABLE_SIZE; 数据->left3_phase += 9; if( 数据->left3_phase >= TABLE_SIZE ) 数据->left3_phase -= TABLE_SIZE; 数据->right3_phase += 11;/* 更高的音高,这样我们就可以区分左右。*/ 如果(数据->right3_phase >= TABLE_SIZE)数据->right3_phase -= TABLE_SIZE; } 返回pa继续; } /* * 播放完成时,portaudio 会调用此例程。 */ 静态无效流完成(无效*用户数据) { paTestData *data = (paTestData *) userData; printf("流完成:%s\n", data->message ); } /************************************************* ******************/ 诠释主要(无效); 诠释主要(无效) { PaStreamParameters 输出参数; PaStream *流; PaError 错误; paTestData 数据; 诠释我; printf("PortAudio 测试:输出正弦波。SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER); /* 初始化正弦波表 */ for(i=0;i<TABLE_SIZE;i++) { data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. ); } data.left_phase = data.right_phase = 0; data.left2_phase = data.right2_phase = 0; data.left3_phase = data.right3_phase = 0; 错误 = Pa_Initialize(); if( err != paNoError ) 转到错误; outputParameters.device = Pa_GetDefaultOutputDevice(); /* 默认输出设备 */ if (outputParameters.device == paNoDevice) { fprintf(stderr,"错误:没有默认输出设备。\n"); 转到错误; } outputParameters.channelCount = 6; /* 5.1 声道输出 */ outputParameters.sampleFormat = paFloat32; /* 32 位浮点输出 */ outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency; outputParameters.hostApiSpecificStreamInfo = NULL; 错误 = Pa_OpenStream( &溪流, NULL, /* 没有输入 */ &输出参数, 采样率, FRAMES_PER_BUFFER, paClipOff, /* 我们不会输出超出范围的样本,所以不要费心剪裁它们 */ Patest回调, &数据 ); if( err != paNoError ) 转到错误; sprintf(data.message,“无消息”); err = Pa_SetStreamFinishedCallback(stream, &StreamFinished); if( err != paNoError ) 转到错误; 错误 = Pa_StartStream( 流 ); if( err != paNoError ) 转到错误; printf("播放 %d 秒。\n", NUM_SECONDS ); Pa_Sleep(NUM_SECONDS * 1000); 错误 = Pa_StopStream( 流 ); if( err != paNoError ) 转到错误; 错误 = Pa_CloseStream( 流 ); if( err != paNoError ) 转到错误; Pa_Terminate(); printf("测试完成。\n"); 返回错误; 错误: Pa_Terminate(); fprintf( stderr, "使用 portaudio 流时出错\n" ); fprintf(stderr, "错误号: %d\n", err ); fprintf(stderr, "错误信息: %s\n", Pa_GetErrorText( err ) ); 返回错误; }