2015-08-31 1 views
0

Я нашел код из Интернета, сначала я играю в волновой файл и не проблема, тогда я снова играю wav и появляюсь ошибка в 48 раз. Я знаю ошибку из функции waveOutOpen.Ошибка waveOutOpen при воспроизведении wav больше раз [delphi]

Это мой код:

unit Unit1; 

interface 

uses 
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, 
    Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls; 

type 
    TForm1 = class(TForm) 
    Button1: TButton; 
    Edit1: TEdit; 
    procedure Button1Click(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

var 
    Form1: TForm1; 

implementation 
uses MMSystem; 

{$R *.dfm} 


var 

    buf: Array of byte; 
    wh: TWaveHdr; 
    hOut: HWAVEOUT; 
    fmt: TWaveFormatEx; 
    count: integer; 


function GetWaveFmtData(path: string; var fmt: TWaveFormatEx): Boolean; 
var 
    hFile: HMMIO; 
    ckiRIFF,ckiFmt,ckiData: TMMCKInfo; 
begin 
    Result := False; 
    hFile := mmioOpen(PChar(path), nil, MMIO_READ); 
    if hFile = 0 then Exit; 

    ZeroMemory(@ckiRIFF, SizeOf(TMMCKInfo)); 
    ZeroMemory(@ckiFmt, SizeOf(TMMCKInfo)); 
    ZeroMemory(@ckiData, SizeOf(TMMCKInfo)); 

    ckiRIFF.fccType := mmioStringToFOURCC('WAVE', 0); 
    ckiFmt.ckid := mmioStringToFOURCC('fmt', 0); 
    ckiData.ckid := mmioStringToFOURCC('data', 0); 

    ZeroMemory(@fmt, SizeOf(TWaveFormatEx)); 

    mmioDescend(hFile, @ckiRIFF, nil, MMIO_FINDRIFF); 

    if (ckiRIFF.ckid = FOURCC_RIFF) and (ckiRIFF.fccType = mmioStringToFOURCC('WAVE',0)) and 
    (mmioDescend(hFile, @ckiFmt, @ckiRIFF, MMIO_FINDCHUNK) = MMSYSERR_NOERROR) and 
    (mmioRead(hFile, @fmt, ckiFmt.cksize) = ckiFmt.cksize) and 
    (mmioAscend(hFile, @ckiFmt, 0) = MMSYSERR_NOERROR) and 
    (mmioDescend(hFile, @ckiData, @ckiRIFF, MMIO_FINDCHUNK) = MMSYSERR_NOERROR) then 
    begin 
    SetLength(buf, ckiData.cksize); 
    Result := (mmioRead(hFile, PAnsiChar(buf), ckiData.cksize) = ckiData.cksize); 
    end; 

    mmioClose(hFile, 0); 
end; 


Procedure CallBack(
    hwo :HWAVEOUT; 
    uMsg :UINT ; 
    dwInstance :DWORD; 
    dwParam1 :DWORD; 
    dwParam2 :DWORD 
);stdcall; 
begin 
    {Need check the message here but for now lets just make sure 
    that we get called } 
    ShowMessage('WaveOut'); 
end; 



procedure TForm1.Button1Click(Sender: TObject); 
const 
    path = 'fire.wav'; 

begin 

    GetWaveFmtData(path, fmt); 

    wh.lpData := PAnsiChar(buf); 
    wh.dwBufferLength := Length(buf); 
    wh.dwBytesRecorded := 0; 
    wh.dwUser := 0; 
    wh.dwFlags := 0; 
    wh.dwLoops := 1; 
    wh.lpNext := nil; 
    wh.reserved := 0; 

    //waveOutClose(hOut); 

    if waveOutOpen(@hOut, WAVE_MAPPER, @fmt, DWORD(@CallBack), 
    Handle,WAVE_MAPPED and CALLBACK_FUNCTION) = MMSYSERR_NOERROR then 
    begin 
    count:=count+1; 
    Edit1.Text:=IntToStr(count); 
    end; 

    waveOutPrepareHeader(hOut, @wh, SizeOf(TWaveHdr)); 
    waveOutWrite(hOut, @wh, SizeOf(TWaveHdr)); 

end; 

end. 

Кстати, функция CallBack не работает, пожалуйста, какой-либо один помочь мне! Full code. Извините за мой английский.

+0

Вы говорите, что вы получаете ошибку 42 от волновых функций? Используйте ['waveOutGetErrorText()'] (https://msdn.microsoft.com/en-us/library/windows/desktop/dd743858%28v=vs.85%29.aspx), чтобы преобразовать код ошибки в строку. – andlabs

+0

Я хочу сказать, что при воспроизведении аудио 48 раз он будет отключен и не будет звука. Хотя я хочу играть звук навсегда, пока я не хочу закрыть его. –

+0

У меня есть опыт работы с wav-файлами, а обратный вызов не является надежным. У меня была обратная связь, работающая на некоторых машинах, а не с другими, и работающая одна и та же машина иногда, а не другие. В конце концов мне пришлось прибегнуть к первому методу безопасности чтения заголовка, посмотреть, как долго он должен играть, и запустить таймер через несколько более длительный период, чтобы файл был закрыт. Ужасно и неприятно, но на 100% надежнее. – Dsm

ответ

0

Неразумно ожидать, что сможете воспроизводить бесконечно много сообщений одновременно. предположительно каждое сообщение является MP3 или MP4, поэтому, хотя они быстрее декодируются, чем кодируются, они не будут бесконечно быстрыми. Затем результирующие образцы волн должны быть объединены вместе, гарантируя, что нет результирующего числового переполнения, что может привести к серьезным искажениям в худшем случае или отсечению в лучшем случае. Все это требует времени. Есть также соображения памяти, но время, скорее всего, будет фактором. Таким образом, драйвер, вероятно, ограничит количество звуков, которые он может воспроизвести в любой момент, чтобы иметь возможность воспроизводить звуки достаточно быстро и без искажений. Если это не так, могут возникнуть проблемы с переполнением.

Большинство аудио традиционно 24 бит стерео (48 бит), поэтому драйвер, основанный на 64-битной технологии, скорее всего, начнет испытывать проблемы переполнения после слияния, в лучшем случае, около 40 выборок. 32-разрядные драйверы, скорее всего, будут сталкиваться с проблемами намного раньше.

+0

Спасибо Dsm. На данный момент я использую компонент DSpack вместо wavout. Все хорошо для меня, однако этот компонент, похоже, не может воспроизводить аудио из Memorystream. –

Смежные вопросы