Я ищу идеи о том, как обработать повторный запуск конвертов для новых заметок в монофонической установке сэмплера, вызывающих щелчки, если конверт предыдущей заметки еще не закончен.В текущей настройке экземпляр предыдущей заметки уничтожается на месте, когда запускается новая заметка (вызов метода synth.stop), вызывая щелчок, поскольку конверт не получает шанса закончить и достичь 0 тома.Любые намеки приветствуются.
Я также добавил в приведенный ниже код свое собственное неудовлетворительное решение, подавляя усиление голоса до 0, а затем переводя голос в спящий режим на 70 мс.Это вносит задержку в 70 мс во взаимодействие с пользователем, но избавляет от любых кликов.Любые значения ниже 70 мс во сне не решают щелчок.
В настоящий момент переменная является общедоступной статической, поэтому я все еще могу поиграть с тем, куда я их вызываю.
Здесьмой код слушателя:
buttonNoteC1Get.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
buttonNoteC1Get.setBackgroundColor(myColorWhite); // reset gui color
if (sample.getSustainBegin() > 0) { // trigger release for looping sample
ampEnv.dataQueue.queue(ampEnvelope, 3, 1); // release called
}
limit = 0; // reset action down limiter
return true;
}
if (limit == 0) { // respond only to first touch event
if (samplePlayer != null) { // check if a previous note exists
synth.stop(); // stop instance of previous note
}
buttonNoteC1Get.setBackgroundColor(myColorGrey); // key pressed gui color
samplePitch = octave * 1; // set samplerate multiplier
Sampler.player(); // call setup code for new note
Sampler.play(); // play new note
limit = 1; // prevent stacking of action down touch events
}
return false;
}
}); // end listener
Вот мой код сэмплера
public class Sampler {
public static VariableRateDataReader samplePlayer;
public static LineOut lineOut;
public static FloatSample sample;
public static SegmentedEnvelope ampEnvelope;
public static VariableRateMonoReader ampEnv;
public static MixerMonoRamped mixerMono;
public static double[] ampData;
public static FilterStateVariable mMainFilter;
public static Synthesizer synth = JSyn.createSynthesizer(new JSynAndroidAudioDevice());
// load the chosen sample, called by instrument select spinner
static void loadSample(){
SampleLoader.setJavaSoundPreferred(false);
try {
sample = SampleLoader.loadFloatSample(sampleFile);
} catch (IOException e) {
e.printStackTrace();
}
} // end load sample
// initialize sampler voice
static void player() {
// Create an amplitude envelope and fill it with data.
ampData = new double[] {
envA, 0.9, // pair 0, "attack"
envD, envS, // pair 2, "decay"
0, envS, // pair 3, "sustain"
envR, 0.0, // pair 4, "release"
/* 0.04, 0.0 // pair 5, "silence"*/
};
// initialize voice
ampEnvelope = new SegmentedEnvelope(ampData);
synth.add(ampEnv = new VariableRateMonoReader());
synth.add(lineOut = new LineOut());
synth.add(mixerMono = new MixerMonoRamped(2));
synth.add(mMainFilter = new FilterStateVariable());
// connect signal flow
mixerMono.output.connect(mMainFilter.input);
mMainFilter.output.connect(0, lineOut.input, 0);
mMainFilter.output.connect(0, lineOut.input, 1);
// set control values
mixerMono.amplitude.set(sliderVal / 100.0f);
mMainFilter.amplitude.set(0.9);
mMainFilter.frequency.set(mainFilterCutFloat);
mMainFilter.resonance.set(mainFilterResFloat);
// initialize and connect sampler voice
if (sample.getChannelsPerFrame() == 1) {
synth.add(samplePlayer = new VariableRateMonoReader());
ampEnv.output.connect(samplePlayer.amplitude);
samplePlayer.output.connect(0, mixerMono.input, 0);
samplePlayer.output.connect(0, mixerMono.input, 1);
} else if (sample.getChannelsPerFrame() == 2) {
synth.add(samplePlayer = new VariableRateStereoReader());
ampEnv.output.connect(samplePlayer.amplitude);
samplePlayer.output.connect(0, mixerMono.input, 0);
samplePlayer.output.connect(1, mixerMono.input, 1);
} else {
throw new RuntimeException("Can only play mono or stereo samples.");
}
} // end player
// play the sample
public static void play() {
if (samplePlayer != null)
{samplePlayer.dataQueue.clear();
samplePlayer.rate.set(sample.getFrameRate() * samplePitch); // set pitch
}
// start the synth engine
synth.start();
lineOut.start();
ampEnv.start();
// play one shot sample
if (sample.getSustainBegin() < 0) {
samplePlayer.dataQueue.queue(sample);
ampEnv.dataQueue.queue( ampEnvelope );
// play sustaining sample
} else {
samplePlayer.dataQueue.queueOn(sample);
ampEnv.dataQueue.queue( ampEnvelope, 0,3);
ampEnv.dataQueue.queueLoop( ampEnvelope, 1, 2 );
}
} }
Неудовлетворительное решение, которое вводит задержку 70 мс, изменяя обработку прослушивателя действий предыдущей заметки на это:
if (limit == 0) {
if (samplePlayer != null) {
mixerMono.amplitude.set(0);
try {
synth.sleepFor(0.07);
synth.stop(); // stop instance of previous note
}catch (InterruptedException e) {
e.printStackTrace();
}
}