我正在尝试开始使用 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 ) );
返回错误;
}