Autor Beitrag
Andreas Pfau
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 997



BeitragVerfasst: So 23.03.03 22:03 
Hallo,

ich will ein Rauschen erzeugen. Kein Problem. Ich habe das so vor:
- Ich erzeuge zwei Buffer mit Rauschen, dern 1. spiele ich ab
- Wenn der 1. fertig ist, spiele ich den 2. Buffer
- Dann bereite ich den 1. Buffer vor, d.h. ich erzeuge ein neues rauschen
- Wenn der 2. Buffer fertig ist, soll wieder der 1. gespielt werden, un dder 2. vorbereitt werden

Wie mache ich das? Ich habe schon mittels einer Callback auf WOM_DONE reagiert, aber das dauert zu lange, bis der 2. Buffer abgespielt wird, da hört man 'ne Unterbrechung.

_________________
Life is a bad adventure, but the graphic is really good!
Andreas Pfau Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 997



BeitragVerfasst: Mo 24.03.03 18:26 
Sorry, das Posting war umsonst. Hab's selber geschafft. Damit es aber doch nicht ganz umsonst war, hier der Code für alle Interessierten:
ausblenden volle Höhe Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
const
 ngSamples = 2500;                      // Anzahl Samples pro Buffer
 ngMax = 2;                             // Anzahl Buffer - 1

var
 ngActive: Boolean;                     // Rauschgenerator aktiv
 ngWaveOut: HWaveOut;                   // Handle des Mappers
 ngSize: Integer;                       // Größe der Blöcke in Byte
 ngBuffer: Array[0..ngMax] Of Pointer;  // Wave-Buffer
 ngHeader: Array[0..ngMax] Of TWaveHdr; // Wave-Header

// Buffer vorbereiten
procedure ngPrepareBuffers;
var
 I, J: Integer;
begin
 // Buffer einzeln durchgehen
 For I := 0 To ngMax Do begin
  // Abgespielte Buffer schließen
  If (ngHeader[I].dwFlags And WHdr_Done <> 0) Then
  WaveOutUnprepareHeader(ngWaveOut, @ngHeader[I], SizeOf(TWaveHdr));

  // Leere Buffer vorbereiten
  If (ngHeader[I].dwFlags And WHdr_Prepared = 0) Then begin
   // Rauschen generieren
   For J := 0 To ngSamples - 1 Do
    PSmallInt(Integer(ngBuffer[I]) + J * 2)^ := Round((Random * 2 - 1) * $7FFF);

   // Vorbereiten
   ngHeader[I].lpData          := PChar(ngBuffer[I]);
   ngHeader[I].dwBufferLength  := ngSize;
   ngHeader[I].dwBytesRecorded := 0;
   ngHeader[I].dwUser          := 0;
   ngHeader[I].dwFlags         := 0;
   ngHeader[I].dwLoops         := 0;
   ngHeader[I].lpNext          := 0;
   ngHeader[I].reserved        := 0;
   WaveOutPrepareHeader(ngWaveOut, @ngHeader[I], SizeOf(TWaveHdr));
  end;
 end;
end;

// Auf abgespielte Buffer reagieren
procedure ngWaveOutProc(Hwo: HWaveOut; uMsg: Integer; dwInstance, dwParam1, dwParam2: DWord); Stdcall;
var
 I: Integer;
begin
 If (Hwo = ngWaveOut) And (uMsg = Wom_Done) Then begin
  // Wenn noch aktiv, neuen Buffer schreiben
  If (ngActive) Then begin
   // Vorbereiteten Buffer suchen
   For I := 0 To ngMax Do
    // Wenn Buffer gefunden, abspielen
    If (ngHeader[I].dwFlags And WHdr_Done = 0) And(ngHeader[I].dwFlags And WHdr_Inqueue = 0) And (ngHeader[I].dwFlags And WHdr_Prepared <> 0) Then begin
     WaveOutWrite(ngWaveOut, @ngHeader[I], SizeOf(TWaveHdr));
     Break;
    end;
  end;
  If (ngActive) Then
   // Wenn noch aktiv, Buffer vorbereiten
   ngPrepareBuffers;
 end;
end;

procedure TMain.Noise1Click(Sender: TObject);
var
 Fmt: TWaveFormatEx;
 I: Integer;
begin
 // Flags setzen
 ngActive := True;

 // Mapper öffnen
 Fmt.cbSize          := SizeOf(Fmt);
 Fmt.wFormatTag      := Wave_Format_Pcm;
 Fmt.nChannels       := 1;
 Fmt.nSamplesPerSec  := 44100;
 Fmt.nAvgBytesPerSec := 44100 * 2 * 1;
 Fmt.nBlockAlign     := 2 * 1;
 Fmt.wBitsPerSample  := 16;
 WaveOutOpen(@ngWaveOut, Wave_Mapper, @Fmt, Integer(@ngWaveOutProc), 0, Callback_Function);

 // Bluffer vorbereiten
 ngSize := ngSamples * 2;
 For I := 0 To ngMax Do
  GetMem(ngBuffer[I], ngSize);
 ngPrepareBuffers;

 // Bluffer schreiben
 WaveOutWrite(ngWaveOut, @ngHeader[0], SizeOf(TWaveHdr));
 WaveOutWrite(ngWaveOut, @ngHeader[1], SizeOf(TWaveHdr));
end;

procedure TMain.Noise0Click(Sender: TObject);
var
 I, C: Integer;
begin
 // Flag setzen
 ngActive := False;

 // Warten bis alle Buffer fertig sind
 Repeat
  C := 0;
  // Alle Buffer durchgehen
  For I := 0 To ngMax Do begin
   // Wenn Buffer fertig oder frei, dann unpreparen
   If (ngHeader[I].dwFlags And WHdr_Done <> 0) Or ((ngHeader[I].dwFlags And WHdr_Prepared <> 0) And (ngHeader[I].dwFlags And WHdr_Inqueue = 0)) Then
    WaveOutUnprepareHeader(ngWaveOut, @ngHeader[I], SizeOf(TWaveHdr));
   // Wenn Buffer fertig, zählen
   If (ngHeader[I].dwFlags And WHdr_Prepared = 0) Then
    Inc(C);
  end;
 Until C = ngMax + 1;

 // Buffer löschen
 For I := 0 To ngMax Do
  FreeMem(ngBuffer[I]);

 // Mapper schließen
 WaveOutClose(ngWaveOut);
end;


Das Form hat 2 Buttons: einer startet den Sound, der andere beendet ihn. Es handelt sich um ein Rauschen (denn anderen Signalformen kann man auch loopen, da wäre das zu viel Aufwand). Es gibt 3 Buffer, immer 2 werden gespielt, und wenn einer fertig ist, wird getauscht. Guckt's auch halt mal an, wenn ihr interesse habt. Auch ein toller Nebenefekkt: Man kann Parameter, z.b. Dämpfung verändern, ohne die wiedergabe zu unterbrechen. Der Nachteil: eine Latez von wenigen ms (je nach Buffergröße). Die Buffergröße sollte nicht zu klein sien, sonst knackt's.

_________________
Life is a bad adventure, but the graphic is really good!