Commit 85c6ed8

Nick committed on
Initial work on synchronization to audio callback
commit 85c6ed8dbb2659149fecbd14a8a16b500e2c424a parent 026a871
5 changed files +73−21
ModifiedSound/sound.pas +54−11
@@ -128,17 +128,25 @@ Bit0 Sound 1 on[1]/off[0]
128 128
129 *) 129 *)
130 130
131 uses Classes; 131 uses Classes, sdl2;
132 132
133 const 133 const
134 SAMPLE_BUFFER_SIZE = 1024; 134 SAMPLE_BUFFER_SIZE = 1024;
135 135
136 type 136 type
137 PSingle = ^Single;
137 TSampleBuffer = record 138 TSampleBuffer = record
138 BufferL, BufferR: array[0..SAMPLE_BUFFER_SIZE] of Integer; 139 BufferL, BufferR: array[0..SAMPLE_BUFFER_SIZE] of Integer;
139 Cursor: Integer; 140 Cursor: Integer;
140 end; 141 end;
141 142
143 procedure StartPlayback;
144 procedure StopPlayback;
145 procedure LockPlayback;
146 procedure UnlockPlayback;
147
148 procedure AudioCallback(userdata: Pointer; stream: PUInt8; len: Integer) cdecl;
149
142 procedure EnableSound; 150 procedure EnableSound;
143 procedure DisableSound; 151 procedure DisableSound;
144 procedure ResetSound; 152 procedure ResetSound;
@@ -153,6 +161,8 @@ procedure EndWritingSoundToStream;
153 var 161 var
154 soundEnable: boolean; 162 soundEnable: boolean;
155 sndRegChange: boolean; 163 sndRegChange: boolean;
164 sndBuffer: ^Single;
165 sndBytesWritten: Integer;
156 snd: array[1..4] of record 166 snd: array[1..4] of record
157 // public: 167 // public:
158 ChannelOFF: boolean; // (un)mute Channel 168 ChannelOFF: boolean; // (un)mute Channel
@@ -170,7 +180,7 @@ var
170 180
171 implementation 181 implementation
172 182
173 uses vars, sdl2, htWaveWriter; 183 uses mainloop, vars, htWaveWriter;
174 184
175 const 185 const
176 SampleSize = SizeOf(Single)*2; 186 SampleSize = SizeOf(Single)*2;
@@ -179,7 +189,7 @@ const
179 TooFullThreshold: Integer = (playbackFrequency div 10)*sizeof(single); //0.1s 189 TooFullThreshold: Integer = (playbackFrequency div 10)*sizeof(single); //0.1s
180 190
181 var 191 var
182 playStream: TSDL_AudioDeviceID; 192 PlayStream: TSDL_AudioDeviceID;
183 bufCycles, bufLVal, bufRVal: integer; 193 bufCycles, bufLVal, bufRVal: integer;
184 lfsr: Cardinal = 0; 194 lfsr: Cardinal = 0;
185 195
@@ -212,7 +222,7 @@ end;
212 222
213 function SoundBufferSize: Integer; 223 function SoundBufferSize: Integer;
214 begin 224 begin
215 Result := SDL_GetQueuedAudioSize(playStream) 225 Result := SDL_GetQueuedAudioSize(PlayStream)
216 end; 226 end;
217 227
218 procedure BeginWritingSoundToStream(Stream: TStream); 228 procedure BeginWritingSoundToStream(Stream: TStream);
@@ -234,6 +244,34 @@ begin
234 WaveWriter.Free; 244 WaveWriter.Free;
235 end; 245 end;
236 246
247 procedure StartPlayback;
248 begin
249 SDL_PauseAudioDevice(PlayStream, 0);
250 end;
251
252 procedure StopPlayback;
253 begin
254 SDL_PauseAudioDevice(PlayStream, 1);
255 end;
256
257 procedure LockPlayback;
258 begin
259 SDL_LockAudioDevice(PlayStream);
260 end;
261
262 procedure UnlockPlayback;
263 begin
264 SDL_UnlockAudioDevice(PlayStream);
265 end;
266
267 procedure AudioCallback(userdata: Pointer; stream: PUInt8; len: Integer)cdecl;
268 begin
269 sndBuffer := PSingle(Stream);
270 while sndBytesWritten < len do
271 z80_decode;
272 sndBytesWritten := 0;
273 end;
274
237 procedure EnableSound; 275 procedure EnableSound;
238 var 276 var
239 Want, Have: TSDL_AudioSpec; 277 Want, Have: TSDL_AudioSpec;
@@ -249,11 +287,10 @@ begin
249 Want.freq := playbackFrequency; 287 Want.freq := playbackFrequency;
250 Want.format := AUDIO_F32; 288 Want.format := AUDIO_F32;
251 Want.channels := 2; 289 Want.channels := 2;
252 Want.samples := 512; //???? 290 Want.samples := 1024; //512;
253 Want.callback := nil; 291 Want.callback := @AudioCallback;
254 292
255 PlayStream := SDL_OpenAudioDevice(nil, 0, @Want, @Have, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE); 293 PlayStream := SDL_OpenAudioDevice(nil, 0, @Want, @Have, 0);
256 SDL_PauseAudioDevice(playStream, 0);
257 294
258 soundEnable := True; 295 soundEnable := True;
259 bufCycles := 0; 296 bufCycles := 0;
@@ -266,7 +303,7 @@ begin
266 if not soundEnable then 303 if not soundEnable then
267 exit; 304 exit;
268 305
269 SDL_CloseAudioDevice(playStream); 306 SDL_CloseAudioDevice(PlayStream);
270 SDL_Quit; 307 SDL_Quit;
271 308
272 soundEnable := False; 309 soundEnable := False;
@@ -293,8 +330,14 @@ begin
293 buf2[1] := Trunc(buf[1]*High(Smallint)); 330 buf2[1] := Trunc(buf[1]*High(Smallint));
294 WaveWriter.WriteBuf(buf2, SizeOf(Smallint)*2); 331 WaveWriter.WriteBuf(buf2, SizeOf(Smallint)*2);
295 end 332 end
296 else 333 else begin
297 SDL_QueueAudio(playStream, @buf, SampleSize); 334 sndBuffer^ := buf[0];
335 Inc(sndBuffer);
336 sndBuffer^ := buf[1];
337 Inc(sndBuffer);
338 Inc(sndBytesWritten, SampleSize);
339 //SDL_QueueAudio(PlayStream, @buf, SampleSize);
340 end;
298 end; 341 end;
299 end; 342 end;
300 343
Modifiedrendertowave.lfm +1−1
@@ -9,7 +9,7 @@ object frmRenderToWave: TfrmRenderToWave
9 ClientWidth = 451 9 ClientWidth = 451
10 OnShow = FormShow 10 OnShow = FormShow
11 Position = poDefault 11 Position = poDefault
12 LCLVersion = '2.0.6.0' 12 LCLVersion = '2.0.8.0'
13 object RenderButton: TButton 13 object RenderButton: TButton
14 Left = 17 14 Left = 17
15 Height = 25 15 Height = 25
Modifiedrendertowave.pas +1−1
@@ -153,7 +153,7 @@ begin
153 153
154 z80_reset; 154 z80_reset;
155 ResetSound; 155 ResetSound;
156 enablesound; 156 //enablesound;
157 157
158 FDCallback := nil; 158 FDCallback := nil;
159 load('hUGEDriver/preview.gb'); 159 load('hUGEDriver/preview.gb');
Modifiedtracker.lfm +1−1
@@ -18,7 +18,7 @@ object frmTracker: TfrmTracker
18 OnShow = FormShow 18 OnShow = FormShow
19 Position = poDefault 19 Position = poDefault
20 ShowHint = True 20 ShowHint = True
21 LCLVersion = '2.0.6.0' 21 LCLVersion = '2.0.8.0'
22 object TreeView1: TTreeView 22 object TreeView1: TTreeView
23 Left = 0 23 Left = 0
24 Height = 555 24 Height = 555
Modifiedtracker.pas +16−7
@@ -869,6 +869,7 @@ begin
869 SymbolTable := ParseSymFile('hUGEDriver/preview.sym'); 869 SymbolTable := ParseSymFile('hUGEDriver/preview.sym');
870 870
871 // Start emulation on the rendered preview binary 871 // Start emulation on the rendered preview binary
872 StopPlayback;
872 EmulationThread.Free; 873 EmulationThread.Free;
873 EmulationThread := TEmulationThread.Create('hUGEDriver/preview.gb'); 874 EmulationThread := TEmulationThread.Create('hUGEDriver/preview.gb');
874 PokeSymbol(SYM_TICKS_PER_ROW, Song.TicksPerRow); 875 PokeSymbol(SYM_TICKS_PER_ROW, Song.TicksPerRow);
@@ -889,9 +890,11 @@ begin
889 TrackerGrid.HighlightedRow := -1; 890 TrackerGrid.HighlightedRow := -1;
890 ToolButton2.ImageIndex := 74; 891 ToolButton2.ImageIndex := 74;
891 892
893 LockPlayback;
892 EmulationThread.Free; 894 EmulationThread.Free;
893 EmulationThread := TEmulationThread.Create('halt.gb'); 895 EmulationThread := TEmulationThread.Create('halt.gb');
894 EmulationThread.Start; 896 UnlockPlayback;
897 //EmulationThread.Start;
895 end; 898 end;
896 899
897 procedure TfrmTracker.OnFD(var Msg: TLMessage); 900 procedure TfrmTracker.OnFD(var Msg: TLMessage);
@@ -1205,8 +1208,11 @@ begin
1205 OrderEditStringGrid.ColWidths[0]:=50; 1208 OrderEditStringGrid.ColWidths[0]:=50;
1206 1209
1207 // Get the emulator ready to make sound... 1210 // Get the emulator ready to make sound...
1211 EnableSound;
1212
1208 EmulationThread := TEmulationThread.Create('halt.gb'); 1213 EmulationThread := TEmulationThread.Create('halt.gb');
1209 EmulationThread.Start; 1214 StartPlayback;
1215 //EmulationThread.Start;
1210 ResetEmulationThread; //TODO: remove this hack 1216 ResetEmulationThread; //TODO: remove this hack
1211 1217
1212 // Start the Oscilloscope repaint timer 1218 // Start the Oscilloscope repaint timer
@@ -1940,7 +1946,7 @@ begin
1940 PokeSymbol(SYM_ROW, 63); 1946 PokeSymbol(SYM_ROW, 63);
1941 end; 1947 end;
1942 end; 1948 end;
1943 EmulationThread.Start; 1949 //EmulationThread.Start;
1944 end 1950 end
1945 end; 1951 end;
1946 1952
@@ -1987,7 +1993,7 @@ begin
1987 PokeSymbol(SYM_CURRENT_ORDER, 2*(OrderEditStringGrid.Row-2)); 1993 PokeSymbol(SYM_CURRENT_ORDER, 2*(OrderEditStringGrid.Row-2));
1988 PokeSymbol(SYM_ROW, 63); 1994 PokeSymbol(SYM_ROW, 63);
1989 end; 1995 end;
1990 EmulationThread.Start; 1996 //EmulationThread.Start;
1991 end 1997 end
1992 else begin 1998 else begin
1993 Highest := Song.Patterns.MaxKey; 1999 Highest := Song.Patterns.MaxKey;
@@ -2082,7 +2088,8 @@ end;
2082 2088
2083 procedure TfrmTracker.ToolButton10Click(Sender: TObject); 2089 procedure TfrmTracker.ToolButton10Click(Sender: TObject);
2084 begin 2090 begin
2085 EmulationThread.Terminate; 2091 //EmulationThread.Terminate;
2092 StopPlayback;
2086 if RenderPreviewROM(Song) then begin 2093 if RenderPreviewROM(Song) then begin
2087 SymbolTable := ParseSymFile('hUGEDriver/preview.sym'); 2094 SymbolTable := ParseSymFile('hUGEDriver/preview.sym');
2088 frmRenderToWave.ShowModal; 2095 frmRenderToWave.ShowModal;
@@ -2098,7 +2105,8 @@ begin
2098 PokeSymbol(SYM_CURRENT_ORDER, 2*(OrderEditStringGrid.Row-1)); 2105 PokeSymbol(SYM_CURRENT_ORDER, 2*(OrderEditStringGrid.Row-1));
2099 PokeSymbol(SYM_ROW, TrackerGrid.Cursor.Y); 2106 PokeSymbol(SYM_ROW, TrackerGrid.Cursor.Y);
2100 2107
2101 EmulationThread.Start; 2108 StartPlayback;
2109 //EmulationThread.Start;
2102 end 2110 end
2103 end; 2111 end;
2104 2112
@@ -2106,7 +2114,8 @@ procedure TfrmTracker.ToolButton3Click(Sender: TObject);
2106 begin 2114 begin
2107 if PreparePreview then begin 2115 if PreparePreview then begin
2108 Playing := True; 2116 Playing := True;
2109 EmulationThread.Start; 2117 StartPlayback;
2118 //EmulationThread.Start;
2110 end; 2119 end;
2111 end; 2120 end;
2112 2121