как реализовать различные типы LFO в периодическом сигнале - PullRequest
0 голосов
/ 26 апреля 2019

Мне нужно реализовать различные типы LFO [низкочастотного генератора] (синус, квадрат, пила, случайный ...?) Для периодического сигнала, создаваемого AudioTrack, и я не знаю как.

Я начинаю с уравнения из вики , но я не очень хорош в математике, и я не знаю, как, например, сделать пилообразную волну LFO для модуляции другого периодического сигнала.

private boolean isRunning;
private double tuneFreqSI;
private double frLFO;
private double ampLFO;
private int sr = 44100;

public void run() {

    super.run();
    isRunning = true;

    int sibuffsize = AudioTrack.getMinBufferSize(sr,
            AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
    AudioTrack siaudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
            sr, AudioFormat.CHANNEL_OUT_MONO,
            AudioFormat.ENCODING_PCM_16BIT, sibuffsize,
            AudioTrack.MODE_STREAM);

    short[] samples = new short[sibuffsize];
    int amp = 32767;
    double twopi = 8. * Math.atan(1.);
    double ph = 0.0;
    double ph1 = 0.0;
    double ph2 = 0.0;
    double LFO = 0;

    // start audio
    try {
        siaudioTrack.play();
    } catch (IllegalStateException e) {

        System.out.println("error play " + e);
    }

    // synthesis loop
    while (isRunning) {

        double fr = tuneFreqSI;
        double fLFO = frLFO;

        for (int i = 0; i < sibuffsize; i++) {

            LFO = ampLFO * Math.sin(ph2);

            samples[i] = (short) (amp * Math.sin(ph + LFO));


            ph += twopi * fr / sr;
            ph2 += twopi * fLFO / sr;
        }
        siaudioTrack.write(samples, 0, sibuffsize);

    }


    siaudioTrack.stop();
    siaudioTrack.release();
}

public void setTuneFreq(double tuneFreq, double frLFO, double ampLFO) {

    this.tuneFreqSI = tuneFreq;
    this.frLFO = frLFO;
    this.ampLFO = ampLFO;
}


public void stopTune() {
    isRunning = false;

    try {
        this.join();
        this.interrupt();
    } catch (InterruptedException e) {
        System.out.println("can´t stop thread +" + e);
        e.printStackTrace();
    }
}

Этомой код, где я генерирую синусоидальную волну.

LFO управляется 2 значениями - частотой (1-30 Гц) и Amplitude, что фактически является глубиной LFO, смешанной с основным сигналом.

генератор для прямоугольной волны, который я использую, выглядит так

samples[i] = (short) (amp * Math.sin(ph+ LFO));

            if (samples[i] > (short) 0.0) {
                samples[i] = (short) amp;
            }

            if (samples[i] < (short) 0.0) {
                samples[i] = (short) -amp;
            }
        ph += twopi * fr / sr;

и генератор волны пилы выглядит так

samples[i] = (short) (amp * (ph / Math.PI + LFO));

        ph += twopi * fr / sr;

эта формула LFO, которую я использую LFO = ampLFO * Math.sin(ph2);, работает очень хорошо,Форма LFO синусовая, и он точно модулирует весь мой сигнал.Мне нужно создать волну НЛО квадратной, пильной или произвольной формы, и я не знаю как.Кто-нибудь может подтолкнуть меня?

...