FMOD объемный звук openframeworks
Хорошо, я надеюсь, что я не испортил это, я искал некоторые ответы, но ничего не могу найти. Я пытаюсь сделать простой сэмплер в openframeworks, используя звуковой проигрыватель FMOD в режиме 3D. Я могу заставить один экземпляр работать нормально (записать новый файл с помощью libsndfilerecorder, а затем воспроизвести его и переместить в окружающее звучание).
Однако я хочу иметь 8 слоев зацикленного звука, которые я могу записывать и заменять по одному слою за раз в прямом эфире. Я получаю много проблем, как только у меня есть более 1 слоя.
Первая часть моего вопроса относится к 3D-режимам FMOD, они относятся к слушателю, поэтому я должен определить положение слушателя для каждого звука (я бы предпочел использовать режим относительной головы, но я вообще не могу заставить эту работу работать). это работает нормально, когда я использую один плеер, но с несколькими игроками работает только последний слушатель, которого я обновляю.
Основная проблема, с которой я столкнулся, заключается в том, что при использовании нескольких плееров в моих новых записях часто возникают искажения и часто смесь других воспроизводимых в данный момент звуков (даже если микрофон их не слышит). Есть ли несовместимость с 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";
}
}
Я стараюсь не прерывать процесс обновления, но я не вижу, в чем дело.
Большое спасибо
2 ответа
Чтобы справиться с искажениями, я думаю, вам нужно будет уменьшить громкость каждого канала при воспроизведении, попробуйте установить громкость на 1/8 от максимальной громкости. отсечение не происходит, поэтому, если сумма звуков> 1,0f, вы будете обрезать, и это будет звучать плохо.
чтобы справиться с перекрестными помехами при записи: я предполагаю, что с выходом происходит какая-то обратная связь, то есть выходной звук возвращается обратно во входной канал, возможно, операционной системой. если вы запускаете другое приложение, которое издает звук, вы также получаете это в своей записи? если это так, то это, вероятно, ваша проблема.
если он работает с одним каналом, попробуйте только 2, вместо того, чтобы прыгать прямо до 8 каналов.
в общем, я бы попытался абстрагировать логику воспроизведения / записи и SoundPlayer/ рекордер в отдельный класс. у вас есть пара логических значений, и действительно легко ошибиться с> 1 логическим значением. Есть ли способ, которым вы можете заменить логическое значение с enum или целочисленной переменной состояния?
РЕДАКТИРОВАТЬ: Я не видел дату на ваш вопрос:D Предположим, вам удалось сделать это к настоящему времени. Может быть, это помогает кому-то еще..
Я не уверен, что смогу ответить на все ваши вопросы, но могу поделиться тем, как я работал с 3D-звуком в FMOD. Я не работал с записью, хотя.
Для моего собственного приложения пользователь может размещать звуки в трехмерном пространстве вокруг себя. Для этого у меня есть только один слушатель и несколько звуков. В своем коде вы делаете слушателя для каждого звука, вы уверены, что это необходимо? Я полагаю, что это приводит к тому, что несколько слушателей получают несколько звуков и выводят их на звуковую карту. Так из второго звука + слушатель, оба слушателя улавливают оба звука? Я не уверен на 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();
}
Я действительно надеялся, что это помогло. Я не очень опытный программист, но именно так я получил FMOD с несколькими звуками для работы в OpenFrameworks и надеюсь, что вы сможете использовать некоторые из них. Я просто выкинул столько кода, сколько смог:D
Мое главное предложение - сделать одного слушателя вместо большего. Также наличие класса для создания звуков полезно, если вы, например, хотите переместить звуки после первоначального размещения.
Надеюсь, это поможет и удачи:)