2010-11-15 20 views
7

Attualmente sto lavorando a un progetto personale: creare una libreria per la sintesi audio in tempo reale in Flash. In breve: strumenti per collegare wavegenarator, filtri, mixer, ecc. E fornire alla scheda audio dati grezzi (in tempo reale). Qualcosa come max/msp o Reaktor.Qualcuno ha qualche consiglio su come programmare la sintesi audio in tempo reale?

Ho già alcune cose di lavoro, ma mi chiedo se l'impostazione di base che ho scritto sia giusta. Non voglio incorrere in problemi successivi che mi costringano a cambiare il nucleo della mia app (anche se ciò può sempre accadere).

Fondamentalmente, ciò che faccio ora è iniziare alla fine della catena, nel punto in cui i dati (grezzi) vengono disattivati ​​(alla scheda audio). Per fare ciò, ho bisogno di scrivere blocchi di byte (ByteArrays) su un oggetto, e per ottenere quel chunk chiedo qualunque modulo sia collegato al mio modulo "Sound Out" per darmi il suo pezzo. Quel modulo fa la stessa richiesta al modulo che è collegato al suo input, e questo continua a succedere fino a quando viene raggiunto l'inizio della catena.

È questo l'approccio giusto? Posso immaginare di imbattersi in problemi se c'è un feedbackloop, o se c'è un altro modulo senza output: se dovessi collegare uno spectrumanalyzer da qualche parte, quello sarebbe un vicolo cieco nella catena (un modulo senza uscite, solo un input). Nella mia attuale configurazione, un tale modulo non funzionerebbe perché comincio solo a calcolare dal modulo di uscita audio.

Qualcuno ha esperienza con la programmazione di qualcosa di simile? Sarei molto interessato a qualche riflessione sull'approccio giusto. (Per chiarezza: non sto cercando specifiche implementazioni di Flash, ed è per questo che non ho taggato questa domanda sotto flash o ActionScript)

risposta

1

Ho fatto una cosa simile qualche tempo fa, e ho usato lo stesso approccio che fai tu - Inizia dalla linea virtuale e traccia il segnale in alto. L'ho fatto per campione, non per buffer; se dovessi scrivere la stessa applicazione oggi, potrei scegliere per-buffer invece, perché sospetto che funzionerebbe meglio.

Lo spettrometro è stato progettato come modulo di inserimento, ovvero funzionava solo se il suo ingresso e la sua uscita erano collegati e passava il suo ingresso all'uscita invariata.

Per gestire il feedback, disponevo di un modulo di supporto speciale che ha introdotto un ritardo di 1 campione e che è stato caricato solo una volta per ciclo.

Inoltre, penso che eseguire tutte le elaborazioni interne con i float, e quindi gli array di float come buffer, sarebbe molto più semplice degli array di byte, e risparmierebbe lo sforzo extra di convertire tra interi e fa galleggiare tutti gli tempo.

0

Nelle versioni successive è possibile avere diverse velocità di pacchetto in diverse parti della rete.

Un esempio potrebbe essere se lo si estenda per trasferire dati su o da disco. Un altro esempio, , sarebbe che le variabili di controllo della velocità dei dati basse, come un ritardo di controllo dell'eco, possano, successivamente, diventare parte della rete. Probabilmente non si desidera elaborare le variabili di controllo con la stessa frequenza con cui elaborate i pacchetti audio, ma sono comunque "in tempo reale" e parte della rete di funzioni. Ad esempio, potrebbero essere necessari livellamenti per evitare transizioni improvvise.

Fintantoché chiamate tutte le funzioni alla stessa velocità e tutte le funzioni richiedono sostanzialmente tempo costante, l'approccio di pull-the-data funzionerà correttamente. Ci sarà essere poco da scegliere tra tirare dati e spingere. Tirare è un po 'più naturale per la riproduzione audio, la spinta è un po' più naturale per la registrazione, ma funziona e finisce per effettuare le stesse chiamate alle funzioni di elaborazione audio sottostanti.

  • Per la spettrometro hai l'emissione di più lavandini per i dati , ma non è un problema. Introduci un link fittizio dal al vero sink. Il collegamento fittizio può causare una richiesta di dati non conforme a . Finché il link fittizio conosce è un manichino e non si preoccupa della mancanza di dati, , tutto sarà OK. Questa è una tecnica standard per ridurre più sink o sorgenti a uno solo.

  • Con questo tipo di rete non si desidera eseguire lo stesso calcolo due volte in un aggiornamento completo. Ad esempio, se si mescola una versione passata e passata di un segnale, non si desidera valutare il segnale originale due volte. Devi fare qualcosa come registrare un valore di tick del timer con ciascun buffer e interrompere la propagazione di pull quando vedi che il valore corrente del tick è già presente. Questo stesso meccanismo ti proteggerà anche dai cicli di feedback nella valutazione.

Quindi, questi due problemi di interesse sono facilmente risolvibili nel quadro attuale.

Valuta corrispondenza dove ci sono diverse velocità dei pacchetti in diverse parti della rete è dove i problemi con l'attuale approccio inizierà. Se stai scrivendo audio su disco, per efficienza ti consigliamo di scrivere pezzi di grandi dimensioni raramente. Non si desidera bloccare il servizio dei più piccoli pacchetti di elaborazione di input e output audio durante tali scritture. Una singola percentuale che tira o spinga la strategia da sola non sarà sufficiente.

Accettate semplicemente che a un certo punto potrebbe essere necessario un modo più sofisticato di aggiornamento rispetto a una rete a tariffa unica. Quando ciò accadrà, avrai bisogno di discussioni per i diversi tassi in esecuzione, o scriverò il tuo semplice programmatore, possibilmente semplice come chiamare le funzioni valutate meno frequentemente una volta in n, per far corrispondere le tariffe. Non è necessario pianificare in anticipo per questo. Le funzioni audio quasi certamente già delegano la responsabilità di garantire che i buffer di input siano pronti per altre funzioni e saranno solo le altre funzioni che devono essere modificate, non le funzioni audio stesse.

L'unica cosa che vorrei consigliare in questa fase è quello di stare attenti a centralizzare buffer audio allocazione, notando che i buffer sono come fenceposts. Non appartengono a una funzione audio , si trovano tra le funzioni audio. La centralizzazione dell'assegnazione del buffer facilita la modifica retrospettiva della strategia di aggiornamento per diverse velocità in diverse parti della rete.