Модераторы: Snowy, Alexeis, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> BASS_StreamCreateFileUser, BASS_FILEPROCS callback-функции 
V
    Опции темы
GuManOiD
Дата 23.4.2009, 14:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 79
Регистрация: 12.9.2005

Репутация: нет
Всего: нет



Доброго дня, форумчане.

IDE: Delphi 2007 update 3

Требуется написать sample программку, которая загружает MP3/WAV файл в TMemoryStream и 
воспроизводит с помощью библиотеки BASS - обязательно используя BASS_StreamCreateFileUser.
BASS_StreamCreateFile не предлагать smile

Вот собственно 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

Починил smile
Изменил 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
PM MAIL   Вверх
dsoft
Дата 1.5.2013, 03:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 23.4.2008

Репутация: нет
Всего: нет



Поздновато увидел пример, но всё равно. Автор не исправил ошибки, а только больше напутал в коде, как следствие те же 1.5 секунды и  AccessViolation.
Цитата

Все ^TMemoryStream поменял на PMemoryStream.

исправить везде на TMemoryStream. После этого начинает играть без сбоев.

Это сообщение отредактировал(а) dsoft - 1.5.2013, 03:22
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Звук, графика и видео"
Girder
Snowy
Alexeis

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делится вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • По вопросам разработки игр стоит заглянуть сюда

FAQ раздела лежит здесь!


Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Girder, Snowy.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Звук, графика и видео | Следующая тема »


 




[ Время генерации скрипта: 0.1152 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.