2010-08-11 14 views

Respuesta

2

Microsoft tiene una Knowledge Base article que le dice cómo se puede reproducir el sonido de la memoria utilizando MCI. Probablemente necesites tener el encabezado del archivo Wave en tu matriz, o copiar los datos correctos durante la primera lectura, pero aparte de eso, debería ser bastante fácil de sobrepasar.

4

Wave Audio Package tiene componente TLiveAudioPlayer. Reproduce audio desde el búfer.

+0

Sí que funcione para mí también. y lo bueno de ella, no hay componentes externos como bass.dll lame.exe etc. – XBasic3000

+0

creo que esta respuesta debería haber sido marcado como el mejor. – Javid

2

La función Win32 API PlaySound puede reproducir audio estándar con codificación RIFF (como audio WAV) desde un bloque de memoria mediante su indicador SND_MEMORY. Alternativamente, si el audio está en los recursos de la aplicación, puede usar el indicador SND_RESOURCE en su lugar.

7

He trabajado mucho con la manipulación de audio PCM. Siempre utilizo esta función durante la reproducción de secuencias cortas de datos de audio de forma de onda de encargo:

var 
    PlaySoundStopper: PBoolean; 
    SoundPlayerActive: boolean = false; 

procedure PlaySound(const Sound: TASSound); 
var 
    hWave: HWAVEOUT; 
    hdr: TWaveHdr; 
    buf: PAnsiChar; 
    fmt: TWaveFormatEx; 
    i: Integer; 
    n: Integer; 
begin 

    try 

    with fmt do 
    begin 
     wFormatTag := WAVE_FORMAT_PCM; 
     nChannels := length(Sound.Channels); 
     nSamplesPerSec := Sound.SampleRate; 
     wBitsPerSample := 32; 
     nAvgBytesPerSec := nChannels * nSamplesPerSec * wBitsPerSample div 8; 
     nBlockAlign := nChannels * wBitsPerSample div 8; 
     cbSize := 0; 
    end; 

    GetMem(buf, fmt.nChannels * length(Sound.Channels[0]) * sizeof(TASWaveformSample)); 
    if length(Sound.Channels) = 1 then 
     CopyMemory(buf, @(Sound.Channels[0, 0]), length(Sound.Channels[0]) * sizeof(TASWaveformSample)) 
    else 
     for i := 0 to high(Sound.Channels[0]) do 
     for n := 0 to high(Sound.Channels) do 
      CopyMemory(buf + sizeof(TASWaveformSample) * (i * fmt.nChannels + n), @(Sound.Channels[n, i]), sizeof(TASWaveformSample)); 

    if waveOutOpen(@hWave, WAVE_MAPPER, @fmt, 0, 0, CALLBACK_NULL) <> MMSYSERR_NOERROR then 
     raise Exception.Create('SoundPlayerThread.Execute: waveOutOpen failed: ' + SysErrorMessage(GetLastError)); 

    ZeroMemory(@hdr, sizeof(hdr)); 
    with hdr do 
    begin 
     lpData := buf; 
     dwBufferLength := fmt.nChannels * length(Sound.Channels[0]) * sizeof(TASWaveformSample); 
     dwFlags := 0; 
    end; 

    try 

     SoundPlayerActive := true; 

     waveOutPrepareHeader(hWave, @hdr, sizeof(hdr)); 
     waveOutWrite(hWave, @hdr, sizeof(hdr)); 
     sleep(500); 

     while waveOutUnprepareHeader(hWave, @hdr, sizeof(hdr)) = WAVERR_STILLPLAYING do 
     if PlaySoundStopper^ then 
     begin 
      waveOutPause(hWave); 
      waveOutUnprepareHeader(hWave, @hdr, sizeof(hdr)); 
      break; 
     end 
     else 
      sleep(100); 

    finally 
     SoundPlayerActive := false; 
     waveOutClose(hWave); 
     FreeMem(buf); 
    end; 

    except 
    on E: Exception do MessageBox(0, PChar(E.ClassName + ': ' + E.Message), 'Sound Playback Error', MB_ICONERROR); 
    end; 
end; 

donde

type 
    TASWaveformSample = integer; // signed 32-bit; -2147483648..2147483647 
    TASWaveformSamples = packed array of TASWaveformSample; // one channel 
    PASSound = ^TASSound; 
    TASSound = record 
    Channels: packed array of TASWaveformSamples; 
    SampleRate: cardinal; 
    end; 

Un quizás mejor manera, es utilizar un hilo para el juego. Entonces hago

var 
    OwnerForm: HWND; // = 0; 
    SndSource: PASSound; // = nil; 
    ThreadPlaying: boolean; // = false; 

type 
    TSoundPlayerThread = class(TThread) 
    private 
    { Private declarations } 
    protected 
    procedure Execute; override; 
    end; 

implementan como

procedure TSoundPlayerThread.Execute; 
var 
    hWave: HWAVEOUT; 
    hdr: TWaveHdr; 
    buf: PAnsiChar; 
    fmt: TWaveFormatEx; 
    i: Integer; 
    n: Integer; 
begin 

    ThreadPlaying := true; 
    try 

    try 

     if not Assigned(SndSource) then 
     Exit; 

     with fmt do 
     begin 
     wFormatTag := WAVE_FORMAT_PCM; 
     nChannels := length(SndSource^.Channels); 
     nSamplesPerSec := SndSource^.SampleRate; 
     wBitsPerSample := 32; 
     nAvgBytesPerSec := nChannels * nSamplesPerSec * wBitsPerSample div 8; 
     nBlockAlign := nChannels * wBitsPerSample div 8; 
     cbSize := 0; 
     end; 

     GetMem(buf, fmt.nChannels * length(SndSource^.Channels[0]) * sizeof(TASWaveformSample)); 
     if length(SndSource^.Channels) = 1 then 
     CopyMemory(buf, @(SndSource^.Channels[0, 0]), length(SndSource^.Channels[0]) * sizeof(TASWaveformSample)) 
     else 
     for i := 0 to high(SndSource^.Channels[0]) do 
      for n := 0 to high(SndSource^.Channels) do 
      CopyMemory(buf + sizeof(TASWaveformSample) * (i * fmt.nChannels + n), @(SndSource^.Channels[n, i]), sizeof(TASWaveformSample)); 

     if waveOutOpen(@hWave, WAVE_MAPPER, @fmt, 0, 0, CALLBACK_NULL) <> MMSYSERR_NOERROR then 
     raise Exception.Create('SoundPlayerThread.Execute: waveOutOpen failed: ' + SysErrorMessage(GetLastError)); 

     ZeroMemory(@hdr, sizeof(hdr)); 
     with hdr do 
     begin 
     lpData := buf; 
     dwBufferLength := fmt.nChannels * length(SndSource^.Channels[0]) * sizeof(TASWaveformSample); 
     dwFlags := 0; 
     end; 

     waveOutPrepareHeader(hWave, @hdr, sizeof(hdr)); 
     waveOutWrite(hWave, @hdr, sizeof(hdr)); 
     sleep(500); 

     while waveOutUnprepareHeader(hWave, @hdr, sizeof(hdr)) = WAVERR_STILLPLAYING do 
     begin 
     sleep(100); 
     if Terminated then 
      waveOutReset(hWave); 
     end; 

     waveOutClose(hWave); 
     FreeMem(buf); 

    except 
     on E: Exception do MessageBox(0, PChar(E.ClassName + ': ' + E.Message), 'TSoundPlayerThread', MB_ICONERROR); 
    end; 

    finally 
    ThreadPlaying := false; 
    end; 
end; 
+0

me gustaría preguntarle más acerca de los PCM. este es mi E-Add [email protected] necesito tu ayuda. – XBasic3000

Cuestiones relacionadas