Newsgroup: it.comp.lang.c++
Titolo: Thread creato da waveOutOpen(..., CALLBACK_THREAD)

Sono alle prese con un'applicazione audio multithreaded in ambiente Win32
(win95), in particolare con le API della serie waveOut... waveIn...
Forse prima o poi proverò a riscrivere il tutto con ActiveMovie (ora forse
lo chiamano DirextX Media), ma per ora non ho l' SDK ed ho quasi finito ciò
che voglio.
Tutto Ok se apro il device audio con waveOutOpen(..., CALLBACK_EVENT) ;
l'unico problema è che ho l'impressione che la "risposta" alla segnalazione
dell'evento _buffer suonato_ non sia così pronta, c'è un po' di latenza e
sono costretto ad usare buffer molto grandi ( 4 buffer da 64KBytes) per non
essere troppo esposto ad audio break se muovo troppe finestre.
Ho dunque provato ad usare una segnalazione basata su messaggi con
waveOutOpen(..., CALLBACK_THREAD). Funziona OK.
Sembra anche che il problema della latenza di risposta sia migliorato:
riesco ad usare 4 buffer da 16384 bytes. Non mi soddisfa ancora però.
La dimensione dei buffer ora mi pare ragionevole(visti altri programmi
commerciali come quelli sotto citati).
Ancora però ho interruzioni dell'audio se durante il play faccio altre cose;
in particolare se faccio apparire e scomparire la barra delle
applicazioni(scorre in modo uniforme su e giù muovendoci sopra il mouse);
questo non accade ad altre applicazioni.
Ho confrontato ciò che ho realizzato con altri programmi audio come GoldWave
e WaveLab( by Steinberg) ed ho fatto alcune scoperte usando Spy++:
1 - con la chiamata waveOutOpen(..., CALLBACK_THREAD) viene creato un nuovo
thread di priorità 9 (la mia applicazione ha priorità 8) ; con la
segnalazione ad eventi nessun nuovo thread è creato.
2 - WaveLab ha un po' di thread a priorità 8 qualcuno 9 ed uno a priorità
10. Credo che quest'ultimo sia quello creato dalla waveOutOpen(...,
CALLBACK_THREAD) che si occupa della segnalazione di buffer libero
(suonato).
3 - GoldWave in modo analogo ha alcuni thread, uno in particolare ha
priorità 23 ! Credo sia quello che si occupa della solita segnalazione.
Se le mie ipotesi sono giuste (cioè se quei thread ad alta priorità nei due
programmi citati sono creati dalla chiamata waveOutOpen(...,
CALLBACK_THREAD) ) allora la domanda è :
    Come si specifila la priorità di quel thread ?
    E' davvero influente ai fini su esposti ?
    Come altrimenti migliorare le "prestazioni" ?
Spero in qualche suggerimento.
Grazie.
Livio Cavallo


Indipendentemente dal sistema di monitoraggio che scegli per
la notifica di WHDR_DONE, presumo che tu abbia dei "gaps"
durante il playback semplicemente perché aspetti la notifica
tramite MM_WOM_DONE prima di mandare in output il
prossimo blocco audio, questo é dovuto ai ritardi nella notifica
che nella reazione della tua applicazione.
Ti consiglio quindi di usare questa procedura:
    - Spedisci i primi due blocchi di dati uno dopo l'altro con
      waveOutWrite subito all'inizio del playback.
    - Dopo di che, ad ogni notifica di MM_WOM_DONE,
      spedisci il prossimo blocco, fino a completamento.
      Con questo metodo otterrai che, finito il primo blocco,
      il sistema inizierà col secondo già in coda, mentre tu
      aggiungerai alla coda il terzo.
      Finito il secondo, il sistema comincerà ad inviare il terzo
      già in coda, mentre tu aggiungerai il quarto e così via.
Inoltre, unicamente per completezza, ti sconsiglio di usare
CALLBACK_EVENT perché WaitForSingleObject terrà in attesa
la thread chiamante fino a completamento dell'evento o del time-out.
Non avrai così più modo, per esempio, di gestire delle pause
(waveOutPause) nel flusso di output oppure di leggere la posizione
(waveOutGetPosition) per visualizzarla come feedback con uno
static-control.
Questo suggerimento ovviamente esula da quei casi in cui vuoi proprio
ottenere l'effetto di mettere in attesa il thread.
Saluti, Neil

static-control.
Concordo. Infatti in realtà ho usato MsgWaitForMultipleObjects che permette
di interrompere il wait all'arrivo di un messaggio.
Livio Cavallo


Ti ho indicato SetThreadPriority semplicemente per illustrarti con quale
funzione é possibile modificare la priorità di una thread.
Capisco che possa poi essere un problema ottenere l'handle della
thread da te richiesta, ma come ti ho detto, non vedo l'utilità di
alterarne la priorità.
In primo luogo, se già usi la procedura che ti ho indicato, non dovresti
più avere delle "gaps" nel flusso di output audio.
(Mi sembrava che ti riferissi a questo quando parlavi di prestazioni).
In secondo luogo, anche con un buffer di soli 16KB e con un formato
audio di 44.1KHz, 16bits stereo, l'esecuzione del suddetto blocco richiede
poco meno di 93 millisecondi, un tempo praticamente infinito.
Durante questo periodo, hai tutto il tempo di aggiungere un nuovo buffer
in coda anche se la notifica di MM_WOM_DONE (o altro) non é subitanea.
(Tieni presente che quando il sistema notifica la fine di esecuzione di un
buffer, un altro é già presente nella coda).
Di conseguenza, anche migliorando la latenza di notifica tramite la
modifica della priorità della thread (ammesso che le due cose siano
collegate), questa si ridurrebbe ad una piccolissima frazione di tempo
rapportata ai 93 ms sopra citati.
Saluti, Neil