好的,我希望我不要搞砸了,我已经找了一些答案,却找不到任何答案。我想在3D模式下使用FMOD声音播放器在openframeworks中制作一个简单的采样器。我可以使单个实例正常工作(使用libsndfilerecorder记录一个新文件,然后播放它并将其移动到环绕声中。
但是我希望有8层循环音频,我可以在现场演出中一次录制和替换一层。一旦我有超过1层,我就会遇到很多问题。
我的问题的第一部分与FMOD 3D模式有关,它是听众相对的,所以我必须为每一个声音定义我的听众的位置(我更喜欢有头部相对模式,但我无法在当我使用单个播放器但多个播放器只有我更新的最后一个监听器实际上有效时,这个工作正常。
我遇到的主要问题是,当我使用多个播放器时,我会在我的新录音中出现失真,并且经常混合其他当前播放的声音(即使麦克风听不到它们)。与libsndfilerecorder和FMOD有不兼容吗?
我在这里初始化球员
for (int i=0; i<CHANNEL_COUNT; i++) {
lvelocity[i].set(1, 1, 1);
lup[i].set(0, 1, 0);
lforward[i].set(0, 0, 1);
lposition[i].set(0, 0, 0);
sposition[i].set(3, 3, 2);
svelocity[i].set(1, 1, 1);
//player[1].initializeFmod();
//player[i].loadSound( "1.wav" );
player[i].setVolume(0.75);
player[i].setMultiPlay(true);
player[i].play();
setupHold[i]==false;
recording[i]=false;
channelHasFile[i]=false;
settingOsc[i]=false;
}
录制时我会卸载文件并确保未加载的播放器位置不会更新。
void fmodApp :: recordingStart(int recordingId){
if (recording[recordingId]==false) {
setupHold[recordingId]=true; //this stops the position updating
cout<<"Start recording Channel " + ofToString(recordingId+1)+" setup hold is true \n";
pt=getDateName() +".wav";
player[recordingId].stop();
player[recordingId].unloadSound();
audioRecorder.setup(pt);
audioRecorder.setFormat(SF_FORMAT_WAV | SF_FORMAT_PCM_16);
recording[recordingId]=true; //this starts the libSndFIleRecorder
}
else {
cout<<"Channel" + ofToString(recordingId+1)+" is already recording \n";
}
}
我就这样停止录音。
void fmodApp::recordingEnd( int recordingId ){
if (recording[recordingId]=true) {
recording[recordingId]=false;
cout<<"Stop recording" + ofToString(recordingId+1)+" \n";
audioRecorder.finalize();
audioRecorder.close();
player[recordingId].loadSound(pt);
setupHold[recordingId]=false;
channelHasFile[recordingId]=true;
cout<< "File recorded channel " + ofToString(recordingId+1) + " file is called " + pt + "\n";
}
else {
cout << "Sorry track" + ofToString(recordingId+1) + "is not recording";
}
}
我注意不要中断更新过程,但我看不出我的错误。
非常感谢
答案 0 :(得分:1)
处理失真,我认为你需要在播放时降低每个频道的音量,尝试将音量设置为最大音量的1/8。没有任何剪辑,所以如果声音的总和&gt; 1.0f你会剪辑,听起来很糟糕。
在录制时处理串扰:我猜你的输出会有某种反馈,即输出声音可能被操作系统反馈到输入通道。如果你运行另一个声音的应用程序,你也可以在你的录音中得到它吗?如果是这样那么那可能是你的问题。
如果它适用于一个频道,只需使用2,而不是直接跳到8个频道。
一般来说,我会尝试将播放/录制逻辑和soundPlayer /录音机抽象为一个单独的类。那里有几个布尔值,用&gt; 1布尔值很容易犯错误。有没有办法可以用枚举或整数状态变量替换布尔值?
答案 1 :(得分:0)
我不确定我是否可以回答你的所有问题,但我可以分享我在FMOD中使用3D声音的方式。我虽然没有录音。
对于我自己的应用程序,用户可以将声音放在自己周围的3D空间中。为此,我只有一个听众和多个声音。在你的代码中,你正在为每个声音做一个听众,你确定这是必要的吗?我想这会导致多个侦听器拾取多个声音并将其输出到声卡。那么从第二个声音+听众那里,两个听众都会听到两个声音?我不是100%肯定,但对我来说听起来似乎是合理的。
我创建了一个类来创建声音对象(和一个监听器)。然后我使用一个向量来存储对象并移动它们来渲染它们。
我的班级SoundBox基本上掌握了FMOD所需的所有东西
制作一个“SoundBox”对象并将其添加到我的音箱矢量中:
SoundBox * box = new SoundBox(box_loc, box_rotation, box_color);
box->loadVideo(ofToDataPath(video_files[soundboxes.size()]));
box->loadSound(ofToDataPath(sound_files[soundboxes.size()]));
box->setVolume(1);
box->setMultiPlay(true);
box->updateSound(box_loc, box_vel);"
box->play();
soundboxes.push_back(box);
SoundBox的构造函数。我在同一个类中为侦听器使用类似的构造函数,但由于侦听器将始终位于我的原点,因此它不接受任何参数,只将所有侦听器位置设置为0.侦听器的构造函数只获取只要我想要制作一个新的,就会调用一次。 (不要介意box_color。在这种情况下,我正在绘制物理盒..):
SoundBox::SoundBox(ofVec3f box_location, ofVec3f box_rotation, ofColor box_color) {
_box_location = box_location;
_box_rotation = box_rotation;
_box_color = box_color;
sound_position.x = _box_location.x;
sound_position.y = _box_location.y;
sound_position.z = _box_location.z;
sound_velocity.x = 0;
sound_velocity.y = 0;
sound_velocity.z = 0;
然后我只是使用for循环来循环播放它们并在它们不播放时播放它们。我也有一些类似的代码来选择它们然后移动。
for(auto box = soundboxes.begin(); box != soundboxes.end(); box++){
if(!(*box)->getIsPlaying())
(*box)->play();
}
我真的希望这会有所帮助。我不是一个非常有经验的程序员,但这就是我在OpenFrameworks中使用多个声音获得FMOD并希望你可以使用它的一些方法。我尽可能多地抛弃了我的代码:D
我的主要建议是让一个听众而不是更多。例如,如果您想在初始放置后重新定位声音,那么创建声音类也很有用。
希望它有所帮助并祝你好运:)