Доброго дня, форумчане.
IDE: Delphi 2007 update 3
Требуется написать sample программку, которая загружает MP3/WAV файл в TMemoryStream и
воспроизводит с помощью библиотеки BASS -
обязательно используя BASS_StreamCreateFileUser.
BASS_StreamCreateFile не предлагать Вот собственно source:
Код |
unit uPCore;
interface
uses Windows, Classes, Bass, uPDecodeStream;
type TBASSCorePlayer = class(TObject) public constructor Create(hwnd:HWND); procedure Free;
function Play :BOOL; function Stop :BOOL; function Pause :BOOL;
function LastError :LongInt; function GetPlaybackLength :Double; function GetPlaybackPosition :Double; function SetPlaybackPosition(seconds:Double) :BOOL;
procedure AssignStream(AStream:TPDecodeStream); private BASSCh: HSTREAM; BASSProcs: BASS_FILEPROCS; end;
procedure proc_close(user : Pointer); stdcall; function proc_len(user: Pointer): QWORD; stdcall; function proc_seek(offset: QWORD; user: Pointer): BOOL; stdcall; function proc_read(buffer: Pointer; length: DWORD; user: Pointer): DWORD; stdcall;
implementation
constructor TBASSCorePlayer.Create(hwnd:HWND); begin inherited Create; BASS_Init(-1, 44100, 0, hwnd, nil); end;
procedure TBASSCorePlayer.Free; begin BASS_Free; inherited Free; end;
function TBASSCorePlayer.GetPlaybackLength :Double; begin Result := BASS_ChannelBytes2Seconds(BASSCh, BASS_ChannelGetLength(BASSCh, BASS_POS_BYTE)); end;
function TBASSCorePlayer.LastError :LongInt; begin Result := BASS_ErrorGetCode; end;
function TBASSCorePlayer.GetPlaybackPosition :Double; begin Result := BASS_ChannelBytes2Seconds(BASSCh, BASS_ChannelGetPosition(BASSCh, BASS_POS_BYTE)); end;
function TBASSCorePlayer.SetPlaybackPosition(seconds:Double) :BOOL; begin Result := BASS_ChannelSetPosition(BASSCh, BASS_ChannelSeconds2Bytes(BASSCh, seconds),BASS_POS_BYTE); end;
procedure TBASSCorePlayer.AssignStream(AStream: TPDecodeStream); begin //BASSCh := BASS_StreamCreateFile(True, AStream.Memory, 0, AStream.Size, 0); BASSProcs.close := proc_close; BASSProcs.length := proc_len; BASSProcs.read := proc_read; BASSProcs.seek := proc_seek;
BASSCh := BASS_StreamCreateFileUser(STREAMFILE_NOBUFFER, 0, BASSProcs, @AStream) end; //CALLBACKS HERE procedure proc_close(user: Pointer); var AStreamInstance: ^TPDecodeStream; begin AStreamInstance := user; //AStreamInstance.Position := 0; //AStreamInstance^.Free; end;
function proc_len(user: Pointer): QWORD; stdcall; var AStreamInstance: ^TPDecodeStream; begin AStreamInstance := user; Result := AStreamInstance^.Size; end;
function proc_seek(offset: QWORD; user: Pointer): BOOL; stdcall; var AStreamInstance: ^TPDecodeStream; NewPosition: Int64; begin AStreamInstance := user; NewPosition := AStreamInstance^.Seek(offset, soFromBeginning); Result := (NewPosition = AStreamInstance^.Position); end;
function proc_read(buffer: Pointer; length: DWORD; user: Pointer): DWORD; stdcall; var AStreamInstance: ^TPDecodeStream; BytesReaded: DWORD; begin AStreamInstance := user; BytesReaded := 0;
BytesReaded := AStreamInstance^.Read(buffer^, length);
if BytesReaded = length then Result := BytesReaded else Result := 0; end;
function TBASSCorePlayer.Play :BOOL; begin Result := BASS_ChannelPlay(BASSCh, False); end;
function TBASSCorePlayer.Stop :BOOL; begin Result := BASS_ChannelStop(BASSCh); end;
function TBASSCorePlayer.Pause :BOOL; begin Result := BASS_ChannelPause(BASSCh) end;
end.
|
Работает класс так:
Создаем TMemoryStream, делаем LoadFromFile mp3/wav файла.
Этот MemoryStream отправляем классу через AssignStream, далее Play (Stop/Pause/SetPlaybackPosition etc.)
Проблема в том, что при попытке воспроизведения mp3 файла - он играет первые полторы секунды, далее валиться
Access Vialation на строку
Код |
BytesReaded := AStreamInstance^.Read(buffer^, length);
|
Вроде по документации callback функции написаны как надо.
Кстати при попытке воспроизвести WAV проигрывание даже не начинается.
Есть догадки?
SOLVEDПочинил
Изменил read и seek.
Но проблема была в указателе на AStreamInstance.
Теперь адрес передается В параметрах AssignStream, а не в теле процедуры как адрес локальной переменной.
Все ^TMemoryStream поменял на PMemoryStream.
Вот рабочий код (кстати, примером с использованием BASS_StreamCreateFileUser в Delphi нет,
может стоит включить куда-нибудь? сам я блога не веду, кому охота поделиться в своем блоге - welcome):
Код |
unit SamplePlayer;
interface
uses Windows, Classes, Bass;
type PMemoryStream = ^TMemoryStream; TBASSCorePlayer = class(TObject) public constructor Create(hwnd:HWND); procedure Free;
function Play :BOOL; function Stop :BOOL; function Pause :BOOL;
function LastError :LongInt; function GetPlaybackLength :Double; function GetPlaybackPosition :Double; function SetPlaybackPosition(seconds:Double) :BOOL;
procedure AssignStream(AStream:PMemoryStream); private BASSCh: HSTREAM; BASSProcs: BASS_FILEPROCS; end;
procedure proc_close(user : Pointer); stdcall; function proc_len(user: Pointer): QWORD; stdcall; function proc_seek(offset: QWORD; user: Pointer): BOOL; stdcall; function proc_read(buffer: Pointer; length: DWORD; user: Pointer): DWORD; stdcall;
implementation
constructor TBASSCorePlayer.Create(hwnd:HWND); begin inherited Create; BASS_Init(-1, 44100, 0, hwnd, nil); end;
procedure TBASSCorePlayer.Free; begin BASS_Free; inherited Free; end;
function TBASSCorePlayer.GetPlaybackLength :Double; begin Result := BASS_ChannelBytes2Seconds(BASSCh, BASS_ChannelGetLength(BASSCh, BASS_POS_BYTE)); end;
function TBASSCorePlayer.LastError :LongInt; begin Result := BASS_ErrorGetCode; end;
function TBASSCorePlayer.GetPlaybackPosition :Double; begin Result := BASS_ChannelBytes2Seconds(BASSCh, BASS_ChannelGetPosition(BASSCh, BASS_POS_BYTE)); end;
function TBASSCorePlayer.SetPlaybackPosition(seconds:Double) :BOOL; begin Result := BASS_ChannelSetPosition(BASSCh, BASS_ChannelSeconds2Bytes(BASSCh, seconds),BASS_POS_BYTE); end;
procedure TBASSCorePlayer.AssignStream(AStream: PMemoryStream); begin //BASSCh := BASS_StreamCreateFile(True, AStream.Memory, 0, AStream.Size, 0); BASSProcs.close := proc_close; BASSProcs.length := proc_len; BASSProcs.read := proc_read; BASSProcs.seek := proc_seek;
BASSCh := BASS_StreamCreateFileUser(STREAMFILE_NOBUFFER, 0, BASSProcs, @AStream) end; //CALLBACKS HERE procedure proc_close(user: Pointer); var AStreamInstance: PMemoryStream; begin AStreamInstance := user; AStreamInstance.Position := 0; //AStreamInstance^.Free; end;
function proc_len(user: Pointer): QWORD; stdcall; var AStreamInstance: ^TMemoryStream; begin AStreamInstance := user; Result := AStreamInstance^.Size; end;
function proc_seek(offset: QWORD; user: Pointer): BOOL; stdcall; var AStreamInstance: ^TMemoryStream; NewPosition: Int64; begin AStreamInstance := user; NewPosition := AStreamInstance^.Seek(offset, soFromBeginning); Result := (NewPosition < AStreamInstance^.Size); end;
function proc_read(buffer: Pointer; length: DWORD; user: Pointer): DWORD; stdcall; var AStreamInstance: ^TMemoryStream; BytesReaded: DWORD; begin AStreamInstance := user;
Result := AStreamInstance^.Read(buffer^, length); end;
function TBASSCorePlayer.Play :BOOL; begin Result := BASS_ChannelPlay(BASSCh, False); end;
function TBASSCorePlayer.Stop :BOOL; begin Result := BASS_ChannelStop(BASSCh); end;
function TBASSCorePlayer.Pause :BOOL; begin Result := BASS_ChannelPause(BASSCh) end;
end.
|
Это сообщение отредактировал(а) GuManOiD - 24.4.2009, 15:19