Vraag & Antwoord

Programmeren

'klikloos' loopen binnen DirectSound buffers. Hoe

2 antwoorden
  • Hallo mensen. Ik heb een probleempje met het loopen binnen DirectSound buffers. Handig te weten is misschien het feit dat het over een sample gaat van een orgelpijp, opgenomen in een ruimte met 2 seconden nagalm. De situatie is als volgt: Ik heb een sample. Deze bestaat uit 3 delen, en het idee is dat hij 'bespeeld' kan worden met een MIDI-keyboard. Zodra de toets op het kb ingedrukt wordt, moet de sample uiteraard gaan spelen. Logisch. Maar, de sample moet blijven spelen als de toets ingedrukt BLIJFT !! Welnu, in mijn geval kan ik niet gewoon IDirectsoundbuffer.Play(0,0,1) aanroepen oftewel de sample 'loopend' afspelend, want het begin en einde van de sample mogen niet herhaald worden. Het is dus de bedoeling dat alleen het middenste deel van de sample, tussen twee vast bepaalde punten - in mijn voorbeeld L1 en L2 - geloopt moet worden terwijl de toets ingedrukt blijft. De volgorde moet dus zijn : TOETS INDRUK : Sample speelt af AANGEKOMEN BIJ einde Loop-gedeelte : CurrentPlayPosition wordt terug gezet naar begin loop-gedeelte TOETS LOSLAAT : CurrentPlayPositoin wordt geset naar einde loop-gedeelte en de buffer speelt de sample verder af totdat deze afgelopen is. (nagalm stukje) Ik heb zelf al bedacht om per sample 3 buffers te gebruiken, en het loopgedeelte in de middelste buffer te stoppen. Als ik ze dan achter elkaar afspeel blijkt er geen fatsoenlijke loop te makne zijn, je hoort de klikjes van de overgangen. het verwisselen van de Current Playing Buffer kost teveel tijd, enkele milliseconden zelfs. Nu wil ik het dus binnen 1 sample houden en met setCurrentPlayPosition doen. Maar ook nu hoor ik klikjes. Ik denk dat het aan mijn manier ligt van 'detecteren' wanneer currentPlayPosition gelijk is aan L2 (einde loopgedeelte), ik gebruik Sleep(ms: integer) en die werkt maar tot op de millisec oftewel met 1000 hertz. en ik vrees dat ik een hogere triggerfrequentie nodig heb, de sample speelt immers af met 44100 hertz. Ik hoop dat jullie mij kunnen helpen om dit probleem op te lossen ! [Mijn (Delphi3) code:] ------------------------------------------------------------------------------ // i:\testsamp.wav loopgedeelte (splwaarden): 35319 - 51621 samplesPerSecond := lpwfxFormat.nSamplesPerSec; // channels en bits/spl opvragen om te kunnen converteren van // sampleNRs(in de editboxen) naar byteNRs. multiplyier := lpwfxFormat.nChannels * lpwfxFormat.wBitsPerSample div 8; aantalkeren := strtoint(edit_loopaantal.Text); //beginpunt loop L1 := StrToInt(edit_from.Text);// * multiplyier; // conv sampNR naar byteNR //eindpunt loop L2 := StrToInt(edit_to.Text);// * multiplyier; //wat onhandig maar goed... // sleeptime1 = tijd in ms van begin tot begin loop-gedeelte // sleeptime2 = tijd in ms van begin loop-gedeelte tot eind loop-gedeelte exsleeptime1 := (1000 * L1) / samplesPerSecond; // in millisec exsleeptime2 := (1000 * (L2-L1)) / samplesPerSecond; // in millisec strsleeptime1 := FloatToStr(exsleeptime1); strsleeptime2 := FloatToStr(exsleeptime2); intsleeptime1 := StrToInt(Copy(strsleeptime1, 1, Pos(',', strsleeptime1)-1)); intsleeptime2 := StrToInt(Copy(strsleeptime2, 1, Pos(',', strsleeptime2)-1)); // zet de buffer aan het spelen buffer.SetCurrentPosition(0); buffer.play(0,0,0); // speel 1e deel sample sleep(intsleeptime1); // in millisec if aantalkeren = 1 then begin // 2e (LOOP-) deel sample Log1('Playing 2nd (LOOP-) part'); sleep(intsleeptime2); // in millisec Log2('Done'); end else for i := 1 to aantalkeren-1 do begin // 2e (LOOP-) deel sample sleep(intsleeptime2); // in millisec buffer.SetCurrentPosition(L1*Multiplyier); buffer.getCurrentPosition(dwCurrentPlayCursor, lpdwCurrentWriteCursor); end; // 3e deel sample speelt vanzelf af omdat setCurrentPosition niet meer is aangeroepen. end; ------------------------------------------------------------------------------
  • [quote:a5174a2b98="musicom76"] De volgorde moet dus zijn : TOETS INDRUK : Sample speelt af AANGEKOMEN BIJ einde Loop-gedeelte : CurrentPlayPosition wordt terug gezet naar begin loop-gedeelte TOETS LOSLAAT : CurrentPlayPositoin wordt geset naar einde loop-gedeelte en de buffer speelt de sample verder af totdat deze afgelopen is. (nagalm stukje) Ik heb zelf al bedacht om per sample 3 buffers te gebruiken, en het loopgedeelte in de middelste buffer te stoppen. Als ik ze dan achter elkaar afspeel blijkt er geen fatsoenlijke loop te makne zijn, je hoort de klikjes van de overgangen. het verwisselen van de Current Playing Buffer kost teveel tijd, enkele milliseconden zelfs. Nu wil ik het dus binnen 1 sample houden en met setCurrentPlayPosition doen. Maar ook nu hoor ik klikjes. Ik denk dat het aan mijn manier ligt van 'detecteren' wanneer currentPlayPosition gelijk is aan L2 (einde loopgedeelte), ik gebruik Sleep(ms: integer) en die werkt maar tot op de millisec oftewel met 1000 hertz. en ik vrees dat ik een hogere triggerfrequentie nodig heb, de sample speelt immers af met 44100 hertz. Ik hoop dat jullie mij kunnen helpen om dit probleem op te lossen ! [Mijn (Delphi3) code:] ------------------------------------------------------------------------------ // i:\testsamp.wav loopgedeelte (splwaarden): 35319 - 51621 samplesPerSecond := lpwfxFormat.nSamplesPerSec; // channels en bits/spl opvragen om te kunnen converteren van // sampleNRs(in de editboxen) naar byteNRs. multiplyier := lpwfxFormat.nChannels * lpwfxFormat.wBitsPerSample div 8; [/quote:a5174a2b98] [quote:a5174a2b98="musicom76"] aantalkeren := strtoint(edit_loopaantal.Text); //beginpunt loop L1 := StrToInt(edit_from.Text);// * multiplyier; // conv sampNR naar byteNR //eindpunt loop L2 := StrToInt(edit_to.Text);// * multiplyier; //wat onhandig maar goed... // sleeptime1 = tijd in ms van begin tot begin loop-gedeelte // sleeptime2 = tijd in ms van begin loop-gedeelte tot eind loop-gedeelte exsleeptime1 := (1000 * L1) / samplesPerSecond; // in millisec exsleeptime2 := (1000 * (L2-L1)) / samplesPerSecond; // in millisec strsleeptime1 := FloatToStr(exsleeptime1); strsleeptime2 := FloatToStr(exsleeptime2); intsleeptime1 := StrToInt(Copy(strsleeptime1, 1, Pos(',', strsleeptime1)-1)); intsleeptime2 := StrToInt(Copy(strsleeptime2, 1, Pos(',', strsleeptime2)-1)); [/quote:a5174a2b98] [img:a5174a2b98]http://forum.fok.nl/i/s/nooo.gif[/img:a5174a2b98] [quote:a5174a2b98="musicom76"] // zet de buffer aan het spelen buffer.SetCurrentPosition(0); buffer.play(0,0,0); // speel 1e deel sample sleep(intsleeptime1); // in millisec if aantalkeren = 1 then begin // 2e (LOOP-) deel sample Log1('Playing 2nd (LOOP-) part'); sleep(intsleeptime2); // in millisec Log2('Done'); end else [/quote:a5174a2b98] [quote:a5174a2b98="musicom76"] for i := 1 to aantalkeren-1 do begin // 2e (LOOP-) deel sample sleep(intsleeptime2); // in millisec buffer.SetCurrentPosition(L1*Multiplyier); buffer.getCurrentPosition(dwCurrentPlayCursor, lpdwCurrentWriteCursor); end; [/quote:a5174a2b98] [img:a5174a2b98]http://forum.fok.nl/i/s/nooo.gif[/img:a5174a2b98] [quote:a5174a2b98="musicom76"] // 3e deel sample speelt vanzelf af omdat setCurrentPosition niet meer is aangeroepen. end; ------------------------------------------------------------------------------[/quote:a5174a2b98] Heb je een miniprojectje met de code (en de .wav)?

Beantwoord deze vraag

Weet jij het antwoord op deze vraag? Registreer of meld je aan met je account

Dit is een gearchiveerde pagina. Antwoorden is niet meer mogelijk.