JSyn, звук сирены с использованием генератора, который подается / контролируется /inputInto/daisy-chainedTo другим генератором и константой... и генерирует более одного звука
Я пытался следовать примеру здесь, но он не работает, и я не смог найти другие источники: [ http://www.softsynth.com/jsyn/tutorial/osc_control.php ] [1]
Насколько я могу судить, я точно следовал этому примеру кода (за исключением того, что я узнал, что AddUnit
изменился на Add
с тех пор, как эта веб-страница была обновлена):
[...] заставить частоту слегка колебаться относительно центральной частоты, которая находится в более полезном диапазоне. Мы можем сделать это с помощью AddUnit, чтобы добавить выход генератора к постоянному значению, которое мы можем установить. Мы также можем уменьшить амплитуду первого генератора в меньшем диапазоне.
AddUnit freqAdder = new AddUnit();
sineOsc1.output.connect( freqAdder.inputA ); // pass through adder
freqAdder.output.connect( sineOsc2.frequency ); // control second oscillator freq
freqAdder.inputB.set( 500.0 ); // add constant that will center us at 500 Hz
sineOsc1.amplitude.set( 100.0 ); // reduce offset to +/- 100 Hz
Таким образом, частота sineOsc2 будет равна sineOsc1.output плюс inputB.
Кто-нибудь может увидеть, что не так с моим кодом (ниже)? У меня уже работает простой генератор звука. Я просто не слышу этот второй, более сложный звук, который должен быть похож на сирену.
Это может быть проблема с моим кодированием звука сирены, или это может быть просто проблема с моим кодированием генерации двух звуков. (Есть 2 Synthesizers
требуется? Я пробовал это с 1 и 2 Synthesizers
.) (Требуются ли 2 lineOut? Другие источники в сети говорят "нет".)
Вот мой код с 2 synthesizers
и 1 выход:
(Комментарии в кавычках взяты из другого примера кода. Я лишь немного понимаю, к чему эти комментарии относятся.)
import com.jsyn.JSyn;
import com.jsyn.Synthesizer;
import com.jsyn.unitgen.Add;
import com.jsyn.unitgen.LineOut;
import com.jsyn.unitgen.SineOscillator;
[...]
com.jsyn.Synthesizer synthPCMSonification = JSyn.createSynthesizer();
com.jsyn.Synthesizer synthPCMAlarm = JSyn.createSynthesizer();
// "an instance of Synthesizer"
com.jsyn.unitgen.SineOscillator oscData = new SineOscillator();
SineOscillator oscAlarmWaverEnvelope = new SineOscillator();
SineOscillator oscAlarmComplete = new SineOscillator();
// "a unit"
com.jsyn.unitgen.LineOut oscsLineOut = new LineOut();
// "a unit"
[...]
// "start synthesis engine"
synthPCMSonification.start();
synthPCMAlarm.start();
// "build unit generators"
synthPCMSonification.add(oscData);
//synthPCM.add(oscAlarmWaverEnvelope); //TODO: Figure out if need line
synthPCMAlarm.add(oscAlarmComplete);
synthPCMSonification.add(oscsLineOut);
synthPCMAlarm.add(oscsLineOut);
oscData.frequency.set(LOWEST_FREQUENCY_C);
oscData.amplitude.set(volSonification);
//create a frequency adder for a siren-like alarm
com.jsyn.unitgen.Add oscAlarmFreqAdder = new Add(); //used to be AddUnit
//set the alarm centre frequency
alarmCentreFreq = (LOWEST_FREQUENCY_C
* Math.pow(2, OCTAVES_SPANNED_C + 1));
//This formula centres the alarm one octave
//above the threshold's sonification freqency
alarmWaverFreq = alarmCentreFreq / 10;
//This sets the waver at one tenth of the centre freq
//Unfortunately, the waver appears to need to be the
//same amount above and below the centre
//(linear, vice perceptually-linear (exponential))
System.out.println(alarmCentreFreq + "-Hz alarm centre frequency");
oscAlarmFreqAdder.inputB.set(alarmCentreFreq);
//set the alarm waver envelope
//(alarm will range between centre-waver and centre+waver)
oscAlarmWaverEnvelope.frequency.set(alarmCentreFreq / 10);
//"pass through adder" (??)
oscAlarmWaverEnvelope.output.connect(oscAlarmFreqAdder.inputA);
//(entered this with by starting to type, then hitting [Ctrl]+[Space]!)
//"control the 2nd oscillator frequency" (?)
oscAlarmFreqAdder.output.connect(oscAlarmComplete.frequency);
//set alarm volume
oscAlarmComplete.amplitude.set(volAlarm);
// "connect unit generators"
// connect oscillator to both channels of stereo player
oscAlarmComplete.output.connect(0, oscsLineOut.input, 0);
oscAlarmComplete.output.connect(0, oscsLineOut.input, 1);
// "startUnitGenerators"
// "start execution of units. JSyn 'pulls' data so the only unit
// you have to start() is the last one, in this case our LineOut"
oscsLineOut.start();
Сколько людей там знают и используют JSyn
? Как насчет meta-oscillators
?
Если вы когда-либо подключались разные JSyn
части, или даже просто заставить его выводить более одного звука одновременно, вы знаете больше, чем я...
2 ответа
Есть ряд вещей, которые можно улучшить здесь.
1) Вы создали два синтезатора:
com.jsyn.Synthesizer synthPCMSonification = JSyn.createSynthesizer();
com.jsyn.Synthesizer synthPCMAlarm = JSyn.createSynthesizer();
Это необходимо только в том случае, если вы выполняете синтез не в реальном времени или с другой частотой дискретизации. Я настоятельно рекомендую использовать только один синтезатор. Подключение модулей к синтезаторам или запуск одного и того же модуля на обоих синтезаторах вызовет проблемы. Я подозреваю, что это главная ошибка.
Вы можете иметь несколько модулей LineOut в одном синтезаторе. Или вы можете смешивать автоматически, подключив несколько устройств к LineOut.
2) Я рекомендую начать с одного генератора, подключенного к LineOut. После того, как вы сможете заставить это делать звук, добавьте модуляцию.
3) Вы можете получить экспоненциальную частотную (высотную) модуляцию, используя оптимизированный блок PowerOfTwo.
http://www.softsynth.com/jsyn/docs/javadocs/com/jsyn/unitgen/PowerOfTwo.html
Подключите LFO к блоку PowerOfTwo. Затем используйте модуль умножения для масштабирования центральной частоты. LFO, который идет от +1.0 до -1.0, будет масштабировать частоту вверх и вниз на октаву.
4) В учебнике используется старый JSyn API. Мне нужно обновить его. Обратите внимание, что в новом API JSyn вам редко требуется модуль Add, потому что входные порты будут автоматически суммировать любые подключенные входы.
5) Stackru великолепен, но вы можете получить поддержку от сообщества JSyn из более чем 600 человек, подписавшись на список рассылки JSyn.
(Примечание: я действительно хотел просто добавить это к ответу, который дал @philburk, поскольку его ответ определенно помог, но мои просьбы добавить это к его ответу были отклонены, поэтому я должен дать это как отдельный ответ. Я разрываюсь на должен ли я переместить "принять" к этому ответу или нет, хотя, хотя это фактическое исправление.)
Код в вопросе можно исправить, добавив (или изменив, в случае частотной линии) следующие строки кода:
synthPCM.add(oscAlarmWaverEnvelope) //(this is the line I already suspected I needed)
oscAlarmWaverEnvelope.frequency.set(4.0);
oscAlarmWaverEnvelope.amplitude.set(alarmCentreFreq / 10);
...имея в виду:
- Осциллятор все еще должен быть подключен к синтезатору, даже если он не будет слышен напрямую (и в примере кода отсутствовала строка, подобная этой, возможно потому, что в примере кода предполагалось, что у человека был какой-то предыдущий пример кода из учебника),
- Генератор огибающей должен быть установлен на очень низкую частоту, чтобы его влияние было слышно.
- Генератор огибающей должен иметь амплитуду, и она должна быть порядка частоты, которую нужно изменить, чтобы ее влияние было слышно.