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;
------------------------------------------------------------------------------
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;
------------------------------------------------------------------------------