Domanda

Sto scrivendo un sintetizzatore software e ho bisogno di generare forme d'onda senza limiti e alias in tempo reale con campionamento a 44,1 kHz. La forma d'onda del dente di sega farebbe per ora, dal momento che posso generare un'onda di impulso mescolando due denti di sega insieme, uno invertito e sfasato.

Finora ho provato i seguenti approcci:

  1. Precomputer i campioni di forma d'onda perfettamente bandlimited a un ciclo a diverse frequenze di bandlimit all'avvio, quindi riproducendo i due più vicini miscelati insieme. Funziona bene, immagino, ma non è molto elegante. Sono necessari molti campioni o le "lacune" tra loro sarà ascoltato. Anche l'interpolazione e il missaggio richiedono molta CPU.

  2. L'integrazione di un treno di impulsi sinc compensati in corrente continua per ottenere un'onda a dente di sega. Sembra fantastico, tranne che l'onda si allontana da zero se non si ottiene esattamente la compensazione DC (che ho trovato davvero complicato). Il problema DC può essere ridotto aggiungendo un po 'di perdita all'integratore, ma poi perdi le basse frequenze.

Quindi, la mia domanda è: qual è il solito modo di fare questo? Qualsiasi soluzione suggerita deve essere efficiente in termini di CPU, poiché deve essere eseguita in tempo reale, per molte voci contemporaneamente.

È stato utile?

Soluzione

Esistono molti modi per avvicinarsi alla generazione di forme d'onda bandlimited. Finirai per scambiare i costi di calcolo con la qualità come al solito.

Ti suggerisco di dare un'occhiata a questo sito qui:

http://www.musicdsp.org/

Guarda l'archivio! È pieno di buon materiale. Ho appena fatto una ricerca sulla parola chiave "bandlimited". Il materiale che si apre dovrebbe essere occupato per almeno una settimana.

Btw - Non so se questo è quello che stai cercando, ma ho fatto lo pseudonimo di generazione di forme d'onda ridotta (ad es. non proprio limitata nella banda) un paio di anni fa. Ho appena calcolato l'integrale tra l'ultima e l'attuale posizione del campione. Per le forme d'onda di synth tradizionali puoi farlo piuttosto facilmente se dividi il tuo intervallo di integrazione alle singolarità (ad es. Quando il dente di sega viene ripristinato). Il carico della CPU era basso e la qualità accettabile per le mie esigenze.

Ho avuto gli stessi problemi di deriva, ma l'applicazione di un passaggio alto con una frequenza di taglio molto bassa sull'integrale ha eliminato quell'effetto. Il vero sintetizzatore analogico non scende comunque nella regione dei subhertz, quindi non ti perderai molto.

Altri suggerimenti

Un modo rapido per generare forme d'onda limitate dalla banda è usare i passaggi limitati (BLEP). Generi il passaggio a banda limitata stesso:

inserisci qui la descrizione dell'immagine

e memorizzalo in un wavetable, quindi sostituisci ogni transizione con un passaggio limitato dalla banda, per creare forme d'onda che assomiglino a questo:

inserisci qui la descrizione dell'immagine

Guarda la procedura dettagliata su Sintesi del suono limitata dalla banda .

Dato che questo BLEP non è causale (nel senso che si estende nel futuro), per generare forme d'onda in tempo reale, è meglio usare il passaggio limitato in banda a fase minima, chiamato MinBLEP , che ha lo stesso spettro di frequenza, ma si estende solo al passato:

  

I MinBLEP portano avanti l'idea e   prendere un sinc finestra, eseguire un   ricostruzione della fase minima e quindi   integrare il risultato e memorizzarlo in a   tavolo. Ora per creare un oscillatore   basta inserire un MinBLEP in ciascuno di essi   discontinuità nella forma d'onda. Quindi per   un'onda quadrata si inserisce un MinBLEP   dove si inverte la forma d'onda, per saw   onda si inserisce un MinBLEP in cui il   il valore si inverte, ma si genera il valore   rampa come di consueto.

Questo è quello che mi è venuto in mente, ispirato dalle idee di Nils. Incollalo qui nel caso sia utile per qualcun altro. Ho semplicemente filtrato analiticamente un'onda a dente di sega usando analiticamente il cambiamento di fase dall'ultimo campione come dimensione del kernel (o cutoff). Funziona abbastanza bene, c'è qualche aliasing udibile alle note più alte, ma per un uso normale suona alla grande.

Per ridurre ancora di più l'aliasing, la dimensione del kernel può essere aumentata un po ', rendendola anche 2 * phaseChange ad esempio suona bene, anche se perdi un po' delle frequenze più alte.

Inoltre, ecco un'altra buona risorsa DSP che ho trovato sfogliando SP per argomenti simili: Synthesis ToolKit in C ++ (STK) . È una libreria di classi che ha molti utili strumenti DSP. Ha persino pronto per l'uso generatori di forme d'onda bandlimited. Il metodo che usano è quello di integrare sinc come ho descritto nel mio primo post (anche se immagino che lo facciano meglio di me ...).

float getSaw(float phaseChange)
{
    static float phase = 0.0f;
    phase = fmod(phase + phaseChange, 1.0f);
    return getBoxFilteredSaw(phase, phaseChange);
}

float getPulse(float phaseChange, float pulseWidth)
{
    static float phase = 0.0f;
    phase = fmod(phase + phaseChange, 1.0f);
    return getBoxFilteredSaw(phase, phaseChange) - getBoxFilteredSaw(fmod(phase + pulseWidth, 1.0f), phaseChange);
}

float getBoxFilteredSaw(float phase, float kernelSize)
{
    float a, b;

    // Check if kernel is longer that one cycle
    if (kernelSize >= 1.0f) {
        return 0.0f;
    }

    // Remap phase and kernelSize from [0.0, 1.0] to [-1.0, 1.0]
    kernelSize *= 2.0f;
    phase = phase * 2.0f - 1.0f;

    if (phase + kernelSize > 1.0f)
    {
        // Kernel wraps around edge of [-1.0, 1.0]
        a = phase;
        b = phase + kernelSize - 2.0f;
    }
    else
    {
        // Kernel fits nicely in [-1.0, 1.0]
        a = phase;
        b = phase + kernelSize;
    }

    // Integrate and divide with kernelSize
    return (b * b - a * a) / (2.0f * kernelSize);
}

L'offset CC da un blit - può essere ridotto con un semplice filtro passa-alto! - molto simile a un vero circuito analogico in cui usano un cappuccio di blocco CC!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top