Toon posts:

'klikloos' loopen binnen DirectSound buffers. Hoe ?

Pagina: 1
Acties:

Verwijderd

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

  • JayTaph
  • Registratie: Oktober 1999
  • Laatst online: 28-11-2025

JayTaph

Portability is for canoes.

Weet je zeker dat de "klikjes" komen door directX of door het feit dat je geluidsgolven abrust van + naar - of omgekeerd lopen.

Als je gaat loopen dan kun je het beste op de 0-punten van de geluidsgolf loopen: de speaker hoeft dan namelijk niet als een bonkemongool van helemaal uit naar helemaal in te schieten, wat vaak dat klikkend effect geeft.

Yo dawg, I heard you like posts so I posted below your post so you can post again.


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 10:39

Janoz

Moderator Devschuur®

!litemod

Het lijkt me eigenlijk (net als JayTaph) niet een programmeer probleem. De tikjes komen mij heel bekend voor uit mijn tracker tijd. Het ligt zeer waarschijnlijk toch echt aan de samples.

Het is misschien handig om of op vaste plaatsen over te springen (zodat je altijd de juiste positie hebt) of om de samples te crossfaden.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Verwijderd

Topicstarter
Dat doe ik dus ook.. . ik heb die punten exact in Cool edit uitgezocht, waarbij de golven op het 0punt zitten. Dus eht ligt iig NIET aan de samples.

Maar ik heb inmiddels uitgevonden hoe het moet, met setnotificationpoint ofzo. Maar ... mijn Directsound headerfile is nog van directx 2 :( !
Ik wil er een van directx 8 hebben, maar alle die ik download willen niet werken nij mij...

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

Je moet niet 3 buffers gebruiken, je moet 1 buffer gebruiken waar je zelf steeds je geluid in mixed. Zoals je al zei, er zit tijd tussen het aanpassen van de current play position, of het switchen van buffers.

Je kunt het beste dit doen: maak een buffer, en doe daar 2 notifications in. Een vlak voor de helft, en een vlak voor het eind. Maak dan een afspeel thread, waarin je steeds wacht op de notifications (je notifications zijn events, en met WaitForSingleObject () kun je daarop wachten). Als de eerste notificatie bereikt is vul je de 2e helft van de buffer, als de 2e notification bereikt wordt dan vul je de eerste helft weer.

Je moet zelf bijhouden waar de current play position zich in de sample bevindt, en loopen doe je natuurlijk gewoon door na loop_end weer met loop_start te beginnen.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
Ja, bedankt . Ik denk dat het ook zo ongeveer moet. Ik zit alleen nog wat met het volgende: Zodra de toets vastgehoduen wordt, is het 'volgende' stuk wat je in de buffer zet steeds een gedeelte uit de sample binnen het 'loopgedeelte'. En zodra die toets losgelaten wordt, moet wel DIRECT het bijbehorende geluid (einde van de sample) afgespeeld worden. Die kan dus niet op dat moment nog in je mixbuffer gekopieerd worden.

  • Martin Sturm
  • Registratie: December 1999
  • Laatst online: 13-08 12:34
Verwijderd schreef op 22 April 2003 @ 08:23:
Ja, bedankt . Ik denk dat het ook zo ongeveer moet. Ik zit alleen nog wat met het volgende: Zodra de toets vastgehoduen wordt, is het 'volgende' stuk wat je in de buffer zet steeds een gedeelte uit de sample binnen het 'loopgedeelte'. En zodra die toets losgelaten wordt, moet wel DIRECT het bijbehorende geluid (einde van de sample) afgespeeld worden. Die kan dus niet op dat moment nog in je mixbuffer gekopieerd worden.
Je kunt toch wel direct het afspelen stoppen en naar een volgend notification punt springen oid?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op 22 april 2003 @ 08:23:
Ja, bedankt . Ik denk dat het ook zo ongeveer moet. Ik zit alleen nog wat met het volgende: Zodra de toets vastgehoduen wordt, is het 'volgende' stuk wat je in de buffer zet steeds een gedeelte uit de sample binnen het 'loopgedeelte'. En zodra die toets losgelaten wordt, moet wel DIRECT het bijbehorende geluid (einde van de sample) afgespeeld worden. Die kan dus niet op dat moment nog in je mixbuffer gekopieerd worden.
je kunt de huidige afspeelpos opvragen en dan iets verder dan de huidige pos (om interferentie tussen het lezen van de geluidskaart en het schrijven naar diezelfde positie door jouw proces te voorkomen) te schrijven.

Maar bedenk wel dat er dan weer kliks in komen, je kunt het loop-gedeelte niet zomaar afbreken en dan het eindstuk eraan plakken... je zult het loop-gedeelte moeten laten lopen tot het einde van de loop, en dan pas het einde eraan vast moeten plakken

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
Jamaar is het dan absoluut niet mogelijk om te maken wat ik wil ? Dat is ook niet zo, want het programma Hauptwerk doet hetzelfde. Dan is het dus mogelijk ! De vraag is alleen hoe.

Dat programma doet wat ik wil. Het is alleen zo dat ik zoiets moet maken voor een schoolopdracht !

En als je EN een loop hebt, EN je moet op elk moment naar een bepaald punt springen, ja ik weet niet hoe hij het doet. Maar het zou echt zo moeten zijn dat je dan geen klik hoort. Maar hoe...

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

Je kunt het hooguit bereiken door te crossfaden. Daarbij mix je dus 2 buffers door elkaar, waarbij het volume van de buffer die al speelt van maximaal tot 0 gaat, en die van de nieuwe buffer van 0 tot maximaal.

Dit voorkomt kliks, maar het geluid blijft niet echt natuurgetrouw
Tot het einde van de loop en vervolgens het eindgedeelte van de sample is overigens wel een veelgebruikte methode hoor

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
Dat is waar, alleen het is zo dat het loopgedeelte in de ze toepassing nogal groot is, en de tijd tussen het loslaten van de MIDI-toets en het spelen van het daarbij behorende gedeelte van de sample (echo-geluid) mogen hooguit een paar milliseconden uit elkaar liggne.

Het zou natuurlijk kunnen zijn dat die vent het zo heeft gedaan dat hij de buffer laat spelen totdat er een nulwaarde is, en de richtingscoefficient van de golf dezelfde richting heeft als die van het begin van het einde van de sample. Maar hoe je zo precies kunt timen ?? ik weet het niet.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-08 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

Over het algemeen wordt er gedaan zoals ik zei, alsmede uitgefade, zodat het iig niet heel lang duurt voordat het ook echt is afgelopen.

En dat echo effect is dan een apart effect (dus niet met een sample) wat wordt aangezet zodra de toets wordt losgelaten

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1