Francois,
I don't think the problem is in your code. Is there a balance control somewhere downstream from your code? Its behaving as a balance control would. Windows? Best wishes Angus Date: Sat, 13 Jun 2009 11:53:31 +0200 From: "Francois PIETTE" <francois.pie...@skynet.be> Subject: Generating audio waveforms To: <delphi@elists.org> Message-ID: <965968643f57493391fb095a439da...@ovb.local> Content-Type: text/plain; charset="iso-8859-1"; Format="flowed" Hi ! I'm writing a small application which has to generate audio waveform using the sound card (PCM, 11025KHz, stereo, 8 bits). I'm using waveOutWrite and related API function. For now, I have a single buffer. As I understand, audio samples are one byte for left, one byte for right up to the end of buffer. I compute the waveform (a simple sinusoide for my test, different frequency on each channel), store the bytes in the buffer and play the sound. I use an oscilloscope to see the generated waveform. When I set a single channel, that is having one byte with the computed value and one byte with value 128, I get the correct waveform shown on the oscilloscope whatever channel I compute. But when I compute both channels, I get strange results: left channel is the some of computed left channel and a fraction of right channel; right channel is the sum of right channel and a fraction of left channel. See attached screen dump. I don't understand why this happend ! Any help appreciated. Actual source code: const BUFFERSIZE = 65536; //4860; PI = 3.14159265358979; FREQUENCY = 440; procedure TForm1.Button1Click(Sender: TObject); var WFormat : TWaveFormatEx; WaveHeader : TWaveHdr; Done : THandle; HWOut : HWAVEOUT; I : Integer; Data : array [0..BUFFERSIZE - 1] of Byte; X : Extended; L, R : Extended; Offset1 : Integer; Offset2 : Integer; Caps : TWaveOutCaps; begin ZeroMemory(@WFormat, SizeOf(WFormat)); WFormat.wFormatTag := WAVE_FORMAT_PCM; WFormat.nChannels := 2; WFormat.wBitsPerSample := 8; WFormat.nSamplesPerSec := 11025; WFormat.nBlockAlign := WFormat.nChannels * WFormat.wBitsPerSample div 8; WFormat.nAvgBytesPerSec := WFormat.nSamplesPerSec * WFormat.nBlockAlign; WFormat.cbSize := 0; Done := CreateEvent(nil, FALSE, FALSE, nil); if WaveOutOpen(@hWOut, WAVE_MAPPER, @WFormat, Done, 0, CALLBACK_EVENT) <> MMSYSERR_NOERROR then begin ShowMessage('Sound card cannot be opened.'); Exit; end; if waveOutGetDevCaps(hWOut, @Caps, SizeOf(Caps)) <> MMSYSERR_NOERROR then begin WaveOutClose(hWOut); ShowMessage('WaveOutGetDevCaps failed.'); Exit; end; if (Caps.dwFormats and WAVE_FORMAT_1S08) = 0 then begin WaveOutClose(hWOut); ShowMessage('11025KHz 8 bits Mono is not supported'); Exit; end; FillChar(Data, BUFFERSIZE, 128); if ReverseCheckBox.Checked then begin Offset1 := 1; Offset2 := 0; end else begin Offset1 := 0; Offset2 := 1; end; // ReverseCheckBox.Checked := not ReverseCheckBox.Checked; for I := 0 to (BUFFERSIZE div 2) - 1 do begin if LeftCheckBox.Checked then L := sin(I * 2.0 * PI * FREQUENCY / WFormat.nSamplesPerSec) else L := 0; if RightCheckBox.Checked then R := sin(I * 2.0 * PI * 8.0 * FREQUENCY / WFormat.nSamplesPerSec) else R := 0; // ** scale x to a range of 0-255 (signed char) for 8 bit sound reproduction ** Data[I + I + Offset1] := Byte(Trunc(127 * L + 128)); Data[I + I + Offset2] := Byte(Trunc(127 * R + 128)); end; WaveHeader.lpData := PAnsiChar(@Data); WaveHeader.dwBufferLength := BUFFERSIZE; WaveHeader.dwFlags := 0; WaveHeader.dwLoops := 0; // ** Prepare the header for playback on sound card ** if waveOutPrepareHeader(hWOut, @WaveHeader, SizeOf(WaveHeader)) <> MMSYSERR_NOERROR then begin WaveOutClose(hWOut); ShowMessage('Error preparing Header !'); Exit; end; // ** Play the sound! ** ResetEvent(Done); // Reset our Event so it is non-signaled, it will be signaled again with buffer finished if waveOutWrite(hWOut, @WaveHeader, SizeOf(WaveHeader)) <> MMSYSERR_NOERROR then begin WaveOutClose(hWOut); ShowMessage('Error writing to sound card !'); Exit; end; // ** Wait until sound finishes playing if WaitForSingleObject(Done,INFINITE) <> WAIT_OBJECT_0 then begin WaveOutClose(hWOut); ShowMessage('Error waiting for sound to finish'); Exit; end; // ** Unprepare our wav header ** if (waveOutUnprepareHeader(hWOut, @WaveHeader, SizeOf(WaveHeader)) <> MMSYSERR_NOERROR) then begin WaveOutClose(hWOut); ShowMessage('Error unpreparing header !'); Exit; end; if WaveOutClose(hWOut) <> MMSYSERR_NOERROR then begin CloseHandle(Done); ShowMessage('Sound card cannot be closed.'); Exit; end; CloseHandle(Done); end; -- francois.pie...@overbyte.be The author of the freeware multi-tier middleware MidWare The author of the freeware Internet Component Suite (ICS) http://www.overbyte.be _______________________________________________ Delphi mailing list -> Delphi@elists.org http://lists.elists.org/cgi-bin/mailman/listinfo/delphi