Объемный звук FMOD openframeworks

Хорошо, надеюсь, я не испортил это, я искал некоторые ответы, но ничего не нашел. Я пытаюсь сделать простой сэмплер в openframeworks, используя звуковой проигрыватель FMOD в 3D-режиме. Я могу заставить один экземпляр работать нормально (записать новый файл с помощью 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;  
} 

Когда я записываю, я выгружаю файл и проверяю, не обновляются ли позиции незагруженного проигрывателя.

недействительными fmodApp::recordingStart( int recordId ){

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";  
}  

}

Я стараюсь не прерывать процесс обновления, но я не вижу, где я ошибаюсь.

Огромное спасибо


person fred_dev    schedule 11.06.2012    source источник


Ответы (2)


чтобы справиться с искажениями, я думаю, вам нужно будет уменьшить громкость каждого канала при воспроизведении, попробуйте установить громкость на 1/8 от максимальной громкости. никакого клиппинга не происходит, поэтому, если сумма звуков > 1.0f, вы будете клиппировать, и это будет звучать плохо.

чтобы справиться с перекрестными помехами при записи: я думаю, у вас есть какая-то обратная связь с выходом, то есть выходной звук возвращается во входной канал, возможно, операционной системой. если вы запустите другое приложение, которое воспроизводит звук, вы также получите его в своей записи? если так, то это, вероятно, ваша проблема.

если это работает с одним каналом, попробуйте только с двумя, вместо того, чтобы сразу переходить к 8 каналам.

в общем, я бы попытался абстрагироваться от логики воспроизведения/записи и soundPlayer/recorder в отдельный класс. у вас есть пара логических значений, и очень легко ошибиться с > 1 логическим значением. есть ли способ заменить логические значения перечислением или целочисленной переменной состояния?

person damian    schedule 16.06.2012

РЕДАКТИРОВАТЬ: я не видел дату вашего вопроса: 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

Мое главное предложение — сделать одного слушателя вместо нескольких. Также полезно иметь класс для создания звуков, если вы, например, хотите переместить звуки после первоначального размещения.

Надеюсь поможет и удачи :)

person Thyme    schedule 03.04.2013
comment
Спасибо, это было долго, но в итоге я решил это с чем-то очень похожим на ваше предложение и с ясной головой. Ваше здоровье - person fred_dev; 12.12.2014