Questo sito utilizza cookies, anche di terze parti, per mostrare pubblicità e servizi in linea con il tuo account. Leggi l'informativa sui cookies.
Username: Password: oppure
Windows - I misteri di DirectX 7
Forum - Windows - I misteri di DirectX 7

Avatar
AldoBaldo (Member)
Expert


Messaggi: 544
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 16:21
Martedì, 25/08/2020
Ciao a chi mi legge.

Sto giocando con un programmino inconcludente per vedere cosa riesco a fare con DirectX (lo so, è superato... anch'io sono superato, ma sono un usato garantito), e mi trovo di fronte a un quesito in merito a DirectSound al quale non trovo risposta nella documentazione inclusa nell'SDK. Il quesito riguarda il modo in cui recuperare i buffer "smarriti" da DirectSound tramite Restore(), quando quei buffer sono stati ottenuti tramite DuplicateBuffer() anziché tramite CreateBuffer(). Se te la senti di provare ad aiutarmi a capirci qualcosa di un po' più preciso ed affidabile, riproporrò il quesito in modo più circostanziato.

Nel frattempo, in allegato trovi l'eseguibile del programmino inconcludente, al punto al quale si trova. Si tratta di una specie di giochino che genera suoni in uno spazio stereofonico, tramite procedimenti semi-aleatori. L'ho provato su un apparecchio piuttosto "muscolare" con XP e su uno scassone-lumaca con Windows 7. In entrambi i casi sembra funzionare a dovere (in tante prove ho avuto un solo crash occasionale, e non ho idea delle cause che l'hanno provocato).

In assenza di risposte, lascio cadere il quesito e cerco di andare avanti di testa mia.

Buona giornata!


AldoBaldo ha allegato un file: aleatorio.zip (0 bytes)
Clicca qui per scaricare il file


ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti.
PM Quote
Avatar
Carlo (Member)
Guru


Messaggi: 697
Iscritto: 29/01/2018

Segnala al moderatore
Postato alle 23:54
Martedì, 25/08/2020
Lo zip è zero bytes, non puoi caricare zip più grandi di due MegaByte.

a suo tempo usai le directx per i suoni:
http://www.pierotofy.it/pages/sorgenti/dettagli/19538-Allu ...

Ma credo che tu viaggi in C/C++ come al solito.


in programmazione tutto è permesso
PM Quote
Avatar
AldoBaldo (Member)
Expert


Messaggi: 544
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 0:06
Mercoledì, 26/08/2020
Porc... hai ragione sugli zero byte! Non avevo idea del limite di due MB, e lo zip che ho tentato di allegare è poco oltre i 2.2 MB. Ora ho caricato il file qui: http://tinyurl.com/yy7owutl Tra una manciata di giorni lo cancellerò, perché si trova su uno spazio che mi serve per altre cose (più serie).

Da un punto di vista concettuale non credo che faccia una gran differenza il fatto che DirectX lo si usi con C/C++ o con chissà quale altro linguaggio, quindi se sei (eri) pratico magari puoi indirizzarmi lo stesso. Non per niente ho scritto in questa sezione del forum e non in quella su C/C++...


ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti.
PM Quote
Avatar
Carlo (Member)
Guru


Messaggi: 697
Iscritto: 29/01/2018

Segnala al moderatore
Postato alle 0:36
Mercoledì, 26/08/2020
Ok, visto.

Ti dico una cosa che mi ricordo al volo, volevo riprodurre più suoni contemporaneamente e per azzerare i ritardi ho inizializzato tutti i buffer ci ho caricato tutti i suoni e li ho mandati tutti in play, per ascoltare i suoni giusti ho agito solo sui volumi.

Nel mio caso erano rumori continui in loop che duravano meno di 1 secondo, tu hai delle note, è diverso.


in programmazione tutto è permesso
PM Quote
Avatar
AldoBaldo (Member)
Expert


Messaggi: 544
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 17:43
Mercoledì, 26/08/2020
Sì, anch'io carico subito i suoni che mi servono, anche perché il programmino è davvero minimale e con i gigalioni di ram che circolano sui computer odierni non ci sono certo problemi di disponibilità di memoria. Vista la tipologia dei suoni che ho usato (con carattere percussivo), però il trucco del regolare il volume di suoni perennemente in esecuzione non è adatto. Lo terrò comunque presente per il futuro, che è un'idea che non mi è neppure balenata. Hai visto mai...

Nel frattempo, ho "formalizzato" un po' più in dettaglio il quesito che intendevo porre. E' un quesito molto circoscritto, che riguarda un caso molto delimitato. Eccolo qui...

Codice sorgente - presumibilmente C#

  1. LPDIRECTSOUND gSndMain = NULL;
  2.  
  3. LPDIRECTSOUNDBUFFER gSndNote[QMAX_CAMPIONI_NOTE] = { NULL };
  4. LPDIRECTSOUNDBUFFER gNote[QMAX_BUFFERS_NOTE]     = { NULL };
  5.  
  6. /*==============================================================================
  7. All'inizio dell'esecuzione del programma, con InizializzaSonoro() carico i suoni
  8. che mi occorrono predisponendo con CreateSoundBuffer() un buffer per ciascuno
  9. dei suoni campionati che prevedo di usare. Quegli otto buffer che "nascono" dai
  10. suoni campionati hanno ciascuno la sua copia "fisica" dei dati. A me, però,
  11. occorrono 25 suoni indipendenti, per coprire due ottave cromatiche complete.
  12. Creo quindi con DuplicateSoundBuffer() tre "alias" per ciascuno dei buffer che
  13. ho appena caricato (per l'ultimo, in effetti, ne creo quattro, ma e'
  14. irrilevante).
  15.  
  16. Per come agisce DuplicateSoundBuffer(), gli "alias" creati non dispongono di
  17. dati propri, ma fanno riferimento ai dati in memoria gestiti dai buffer
  18. originali, operando su di essi. Fin qui tutto bene, il meccanismo l'ho compreso.
  19. ==============================================================================*/
  20.  
  21. bool InizializzaSonoro( HWND hwnd ) {
  22.     DWORD esito;
  23.     int i, j;
  24.  
  25.     // ... codice per inizializzare DirectSound ...
  26.    
  27.     // NOTA:
  28.     // DSLoadSoundBuffer() e' una funzione che ho trovato tra gli esempi
  29.     // dell'SDK di DirectX 7; crea un buffer statico con CreateSoundBuffer() e
  30.     // ne "riempie" lo spazio di memoria abbinato usando i dati caricati da una
  31.     // risorsa di tipo WAV
  32.  
  33.     for( i=0; i<QMAX_CAMPIONI_NOTE; ++i ) {
  34.         gSndNote[i] = DSLoadSoundBuffer( gSndMain,MAKEINTRESOURCE(IDR_NOTA+i) );
  35.         if( NULL == gSndNote[i] ) return false;
  36.     }
  37.  
  38.     // i dati dei suoni sono in memoria, ora imposto, a partire dagli otto
  39.     // (QMAX_CAMPIONI_NOTE vale 8) buffers gSndNote[], i venticinque (QMAX_NOTE
  40.     // vale 25) alias che servono per le due ottave cromatiche
  41.    
  42.     esito = 0; // uso questo per una verifica "cumulativa" dei risultati
  43.  
  44.     // le prime tre note, abbinate al primo campione audio
  45.     esito += DS_OK==gSndMain->DuplicateSoundBuffer( gSndNote[0], gNote+0 );
  46.     esito += DS_OK==gNote[0]->SetFrequency( 41600 );
  47.     esito += DS_OK==gSndMain->DuplicateSoundBuffer( gSndNote[0], gNote+1 );
  48.     esito += DS_OK==gNote[1]->SetFrequency( 44100 ); // originale
  49.     esito += DS_OK==gSndMain->DuplicateSoundBuffer( gSndNote[0], gNote+2 );
  50.     esito += DS_OK==gNote[2]->SetFrequency( 46700 );
  51.  
  52.     // le tre note successive, abbinate al secondo campione audio
  53.     esito += DS_OK==gSndMain->DuplicateSoundBuffer( gSndNote[1], gNote+3 );
  54.     esito += DS_OK==gNote[3]->SetFrequency( 41600 );
  55.     esito += DS_OK==gSndMain->DuplicateSoundBuffer( gSndNote[1], gNote+4 );
  56.     esito += DS_OK==gNote[4]->SetFrequency( 44100 ); // originale
  57.     esito += DS_OK==gSndMain->DuplicateSoundBuffer( gSndNote[1], gNote+5 );
  58.     esito += DS_OK==gNote[5]->SetFrequency( 46700 );
  59.  
  60.     // ... eccetera, fino ad esaurire gli otto campioni, arrivando a gNote[24]
  61.  
  62.     return (50==esito); // 25 note per due passaggi ciascuna: 50 passaggi
  63. }
  64.  
  65. /*==============================================================================
  66. In SuonaNota(), uso i venticinque alias dell'array gNote[] come strumento
  67. musicale (un glockenspiel con estensione di due ottave cromatiche).
  68.  
  69. Dalla documentazione, vengo a sapere che DirectSound potrebbe liberare senza
  70. preavviso la memoria abbinata a uno qualsiasi degli otto buffer dell'array
  71. gSndNote[], memoria alla quale fanno riferimento anche i 25 "alias" dell'array
  72. gNote[] da essi ricavati. IN QUEL CASO, sebbene l'errore venga segnalato da
  73. gNote[iNota], occorrerebbe ricreare un buffer che non e' in carico a
  74. gNote[iNota], bensi' all'elemento di gSndNote[] al quale si appoggia
  75. quell'alias.
  76.  
  77. Ecco quindi LA DOMANDA: il ripristino si fa con gNote[iNota]->Restore() (usando
  78. quindi direttamente l'alias) o bisogna risalire al buffer dell'array gSndNote[]
  79. dal quale e' stato ricavato gNote[iNota] e usare sottoporre QUELLO a Restore()?
  80. E in questo secondo caso, dopo avere ricreato e ricaricato i dati in gSndNote[],
  81. occorre compiere qualche operazione sull'alias gNote[iNota] per aggiornare il
  82. collegamento con il buffer originario o e' un processo "automatico"?
  83. ==============================================================================*/
  84.  
  85. void SuonaNota( int iNota ) {
  86.     if( !gSuoniInizializzati ) return;
  87.     if( iNota<0 || iNota>=QMAX_BUFFERS_NOTE ) return;
  88.  
  89.     // ... ci sono parti di codice che non c'entrano
  90.     // nulla con le domande e che taglio per brevita'
  91.    
  92.     HRESULT hr = gNote[iNota]->Play( 0, 0, 0 );
  93.  
  94.     if( DSERR_BUFFERLOST == hr ) {
  95.         // ahi! il buffer e' stato demolito da DirectSound,
  96.         // e questo ci porta al nodo della questione
  97.        
  98.         // occorre ricostituire i dati tramite il buffer originario...
  99.            
  100.         hr = DSReloadSoundBuffer( gNote[iNota],
  101.                  MAKEINTRESOURCE(IDR_CAMPIONENOTA+iNota/BUFFER_PER_NOTA) );
  102.            
  103.         // ...oppure ricostituirli tramite il suo "alias"...
  104.            
  105.         hr = DSReloadSoundBuffer( gSndNote[iNota/BUFFER_PER_NOTA],
  106.                  MAKEINTRESOURCE(IDR_CAMPIONENOTA+iNota/BUFFER_PER_NOTA) );
  107.            
  108.         // ...aggiungendo magari qualche altra operazione per ripristinare
  109.         // il collegamento tra il buffer originario e il suo "alias"?
  110.  
  111.         // al termine del ripristino del buffer, possiamo eseguire il suono
  112.         if( DS_OK == hr ) hr = gSnd[iNota]->Play( 0, 0, 0 );
  113.     }
  114. }



A stima mi verrebbe da pensare che dovrebbe bastare agire sugli "alias", però è solo una supposizione e non mi fido dell'intuito.

Ultima modifica effettuata da AldoBaldo il 26/08/2020 alle 19:03


ATTENZIONE! Sono un hobbista e l'affidabilità delle mie conoscenze informatiche è molto limitata. Non prendere come esempio il codice che scrivo, perché non ho alcuna formazione accademica e rischieresti di apprendere pratiche controproducenti.
PM Quote