Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Звук, графика и видео > Воспроизведение музыки из БД


Автор: CrazyPiggy 7.8.2013, 09:52
Добрый день. Помогите пожалуйста решить проблему.
У меня в программе на Delphi из базы данных выбираются записи содержащие mp3 по определенному условию. 
Мне необходимо сделать так чтобы программа воспроизвела одну запись mp3, пока идет воспроизведение программа должна выполнить какието действия, 
после окончания воспроизведения одной записи происходит воспроизведение другой и программа опять выполняет уже другие действия. И так до конца списка.
Я делал так 
Код

var
 MS:TMemoryStream;
begin
  MS:=TMemoryStream.Create;

 try
 for i:=1 to FIBSprBell.Count do
 begin
    MS.Clear;
    FIBSprBellBELL.SaveToStream(MS);
    PlaySound(MS.Memory,0,SND_MEMORY or SND_SYNC);

   /*Что то выполняется*/

 end;
MS.Free;
end; 

Но при этом программа подвисает пока не прогирает весь звук и только потом продолжает выполнять действия.
Пробовал делать так
Код

PlaySound(MS.Memory,0,SND_MEMORY or SND_ASYNC);

Получалось если дальнейшие действия происходят быстрее чем воспроизводится звук, то он воспроизводится не до конца и начинается воспроизведение следующего звук.
Подскажите пожалуйста что мне делать. как узнать воспроизвелся ли звук до конца и лишь после этого воспроизвести следующий.

Автор: Poseidon 7.8.2013, 11:42
Используй SND_SYNC, но цикл воспроизведения засунь в отдельный поток. Вообще SND_SYNC замораживает выполнение кода пока не будет достигнут конец файла. Для пользователя это похоже на зависание программы. Использование SND_ASYNC позволяет коду выполняться дальше. Поэтому у тебя и получается, что при SND_ASYNC музыка начинает играть и пошло выполнятся твое  /*Что то выполняется*/. Как только оно выполнилось, цикл пошел на следующую итерацию, а следовательно пошел новый вызов PlaySound с уже другим звуком.

Цитата

SND_SYNC    Музыка играется синхронно, и функция не возвращает указатель
  пока не будет конца файла.
SND_ASYNC    Музыка играется асинхронно, и функция возвращает указатель
  сразу после начала проигрывания файла. Чтобы остановить проигрывание, 
  надо вызвать функцию SndPlaySound с параметром lpszSoundName 
  установленным в NULL.


Цитата(CrazyPiggy @  7.8.2013,  09:52 Найти цитируемый пост)
как узнать воспроизвелся ли звук до конца и лишь после этого воспроизвести следующий
Для этого можно использовать флаг SND_NOSTOP. При его использовании функция PlaySound вернет False, если музыка уже проигрывается. Но для твоей задачи, скорее всего, не подойдет, т.к. у тебя идет проход по базе в цикле и на каждую запись есть свой звук и свое  /*Что то выполняется*/.


Я бы посоветовал использовать отдельный поток для PlaySound с флагом SND_SYNC.  /*Что то выполняется*/ можно делать в основном потоке, если это выполняется быстро.

Автор: CrazyPiggy 7.8.2013, 11:53
Дело в том что в Чтото выполняется smile происходит отрисовка определленного рисунка на форме. И я не знаю как его закинуть в поток. А может это все можно решить через Bass? Может там все это както проще? Прекратить воспроизведение можно, вызвав функцию BASS_ChannelStop, а проверить, играет ли еще канал или нет - функцией BASS_ChannelIsActive. Только я не пойму как воспроизвести звук из базы в bass.

Автор: Poseidon 7.8.2013, 12:57
Цитата(CrazyPiggy @  7.8.2013,  11:53 Найти цитируемый пост)
Дело в том что в Чтото выполняется  происходит отрисовка определленного рисунка на форме. 
Давай уточним. Если у нас рисунок отрисовался быстрее, чем проиграл звук, что должно быть? Отрисовка следующего рисунка должна ждать окончания проигрывания? Или следующий (второй) рисунок должен начать отрисовываться под проигрывание первого звука? Уточни более подробно как должно работать.

Цитата(CrazyPiggy @  7.8.2013,  11:53 Найти цитируемый пост)
И я не знаю как его закинуть в поток.
По слову "TThread" ты найдешь кучу сообщений и примеров кода. 

Автор: CrazyPiggy 8.8.2013, 00:18
Цитата

 Уточни более подробно как должно работать

При воспроизведении звука (а это число, которое я складываю из цифр хранящихся в базе в виде mp3) на экране рисуется это самое число которое мигает пока он произносится. При окончании воспроизведения числа, воспроизводится следующее число, которое также отображается графически на экране мигающим. И так далее Чтото типа 153 (сто пятьдесят три идет выборка этих озвучек из БД) и на экране мигает число 153

Автор: Poseidon 8.8.2013, 12:13
Не знаю как реализовано мигание. Если через цикл, то может не получится. Но в общем, если боишься потоков, то можно сделать так:
Код

var
  MS:TMemoryStream;
begin
  MS:=TMemoryStream.Create;
  try
    for i:=1 to FIBSprBell.Count do
    begin
      MS.Clear;
      FIBSprBellBELL.SaveToStream(MS);

      /*Что то выполняется*/

      while not PlaySound(MS.Memory,0,SND_MEMORY or SND_ASYNC or SND_NOSTOP) do
        Application.ProcessMessages;
    end;
  finally
    MS.Free;
  end;
end;

Я скопировал твой код и немного его подправил. Мне не совсем ясно как мы этим циклом переходим на другую запись в БД. Т.е. нет ни Next, ни i не используется. Тебе это виднее. Я лишь показал как можно сделать. Добавить в PlaySound SND_NOSTOP и крутить его в цикле, пока музыка не закончилась. Как только замолчало, так идем на следующую итерацию цикла. Корявенько и я бы у себя так не сделал бы, но как один из вариантов без потоков... Если в /*Что то выполняется*/ свой внутренний цикл, то не получится. Нужно будет этот цикл пихать в наш while...do. Если моргание сделано через какой-нибудь таймер или тому подобное, то пройдет.

Автор: CrazyPiggy 10.8.2013, 16:54
Спасибо за помощь. Разобрался в своей проблеме

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)