Delphirus - прграммирование на delphi
   Все о delphi Delphirus - прграммирование на delphi
blocks.gif
Навигация
 

Главная
Статьи
Базы данных
Графика
Защита
Интернет
Система
Тексты
Мультимедиа
Файлы
Формы и окна
Другое
Советы
Базы данных
Графика
Интернет
Мультимедиа
Система
Тексты
Файлы
Файлы
Исходники
Компоненты
Инфо
Поиск по сайту
Обратная связь
Самое популярное
Аккаунт
Карта сайта

 
story.gif
Delphi: Свой WinAMP в подарочной упаковке
 
Работа со звуком и видео

На свете существует такое огромное количество медиа-плееров, что просто взять и накодить очередной WinAMP-killer стало уже немодно. Многие это проделывали, пытаясь доказать общественности, что их прога чем-то лучше/красивее/функциональнее. Ну, как говорится - флаг им в руки и поезд навстречу, а мы пойдем другим путем - будем делать штучный товар, предназначенный только для одного, но хорошего человека. В подарок.



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

Реквизит

Делать хороший медиа-плеер "с нуля" и на чистом API довольно долго и муторно, поэтому мы воспользуемся пакетом под названием BASS 1.8 от Un4seen developments, который и попал сегодня под мой резекционный нож. Вскрытие показало, что его основу составляет библиотека bass.dll и соответствующий заголовочный файл (я имею в виду Delphi, но она поддерживает еще несколько языков). Содержит эта либа целый набор функций для работы со звуком через DirectSound. Таким образом, ты сможешь проигрывать mp3/mp2, WAV, MOD-музыку, MO3, аудио-компакты, работать с сэмплами, записывать саунд и пользоваться при этом всеми преимуществами DirectX 8.0. Внушительный набор, особенно если ты собираешься кодить игрушки или ди-джейский софт - в подобных прогах итак есть над чем напрячься, поэтому пусть уж хоть работа со звуком будет легкой и приятной.

Сам компонент качай отсюда: http://www.realcoding.net/index.php?files&id=191 . Весит он всего 550 Кб. После распаковки архива главное - не забыть поместить bass.dll в windowssystem, а заголовочный файл - в delphilib и помнить, что bass.dll нужна для работы программы. А то получится, что перепишешь саму прогу на дискету, придешь с ней в гости... а она не работает. Будет весьма торжественный момент, и смеяться над тобой будут даже самые грустные и нетрезвые люди :).

Функции bass.dll - инициализация

Инициализация - вещь архиважная и архинужная. Поэтому товарищи из un4seen напряглись и сделали целых 3 функции для этой цели:

1) function BASS_Init(device: Integer; freq, flags: DWORD; win: HWND): BOOL;

Инициализирует BASS. Здесь:

device: 0 - первое устройство, -1 - по умолчанию, -2 - без звука.

freq - частота. Обычно - 44100.

flags - флаги. Например, BASS_DEVICE_MONO даст монозвук (вспомнишь молодость), а BASS_DEVICE_VOL1000 позволит тебе измерять громкость по шкале от 0 до 1000. Напомню, по умолчанию - до 100. Если такие настройки тебе не нужны, ставь 0.

2) function BASS_CDInit(drive: PChar; flags: DWORD): BOOL;

Инициализирует CD функции.

drive - ставь 0.

flags - флаги - опции для громкости. Один ты уже видел выше (который 1000), а второй выглядит так: BASS_DEVICE_LEAVEVOL. Это громкость по умолчанию.

3) function BASS_Start: BOOL;

Открытие звукового выхода или resume после паузы.

Функции для работы с CD

1) function BASS_CDDoor(open:BOOL): BOOL; Выдвигает лоток сидюка, если ты передал ей TRUE. Если false, то лоток втягивается обратно.

2) function BASS_CDInDrive: BOOL;

Выясняет, есть ли аудио-CD в сидюке. Если есть, то возвращает TRUE.

3) function BASS_CDGetTracks:DWORD;

Получает количество треков на диске. Его, соответственно, и возвращает.

4) function BASS_CDGetTrackLength(track:DWORD):DWORD;

Возвращает длину трека в миллисекундах.

track - номер трека.

5) function BASS_CDPlay(track: DWORD; loop: BOOL; wait: BOOL): BOOL;

Играет заданный трек.

track - номер трека.

loop - если true, то играем циклически, наоборот - один раз.

wait - ждать или нет перед проигрышем.

6) procedure BASS_CDFree;

Освобождает ресурсы, занятые CD-аудио.

Функции для работы со звуковыми файлами

1) function BASS_StreamCreateFile(mem: BOOL; f: Pointer; offset, length, flags: DWORD): HSTREAM;

Создает звуковой поток из локального файла, к каковым относятся mp3, mp2, mp1, OGG и WAV. Файл может быть как на диске, так и в оперативке.

mem - если TRUE, то файл в оперативке. Если FALSE - то на диске. f - имя файла (если он на диске).

offset - смещение, с которого надо начинать. Обычно я начинаю с начала, но если у тебя другое мнение - сообщи его этому аргументу.

length - необходимое количество данных. Если ты хочешь использовать все до конца файла, то просто ставь 0.

flags - ставь 0.

Функция возвращает переменную типа HSTREAM, которая и есть хэндл новорожденного потока.

2) function BASS_StreamCreateURL(URL: PChar; offset: DWORD; flags: DWORD; save: PChar):HSTREAM;

То же, что и предыдущая функция, но поток создается не из локального, а из удаленного файла. Откуда и следуют новые аргументы:

URL - урл к файлу. Может начинаться либо с http://, либо с ftp://.

save - путь, куда класть закачанный файл. Если здесь null, значит не надо никуда сохранять.

3) function BASS_StreamGetLength(handle: HSTREAM): QWORD;

Получает приблизительную длину потока в байтах.

handle - получаем с помощью двух предыдущих функций.

Если размер в байтах тебя не удовлетворяет, воспользуйся функцией BASS_ChannelSeconds2Bytes. В ней нет ничего сложного, но она возвратит тебе уже секунды.

4) function BASS_StreamPlay(handle: HSTREAM; flush: BOOL; flags: DWORD): BOOL;

Играет заданный поток.

handle - хэндл потока.

flush - если false, поток можно приостанавливать, затем играть с места остановки. Если true, то остановка грозит возвращением к началу.

flags - если здесь будет стоять BASS_SAMPLE_LOOP, то поток будет играть ВЕЧНО.

5) function BASS_ChannelPause(handle: DWORD): BOOL;

Ставит паузу в воспроизведении чего угодно - CD, потока, сэмпла. Главное - скормить ей хэндл, который и является единственным аргументом.

6) function BASS_ChannelResume(handle: DWORD): BOOL;

Функция, обратная предыдущей.

7) function BASS_ChannelSetAttributes(handle: DWORD; freq, volume, pan: Integer): BOOL;

Функция, устанавливающая атрибуты воспроизведения заданного канала. Под термином "канал" разработчики понимают все воспроизводимое и записываемое: HCHANNEL/HMUSIC/HSTREAM или CDCHANNEL/RECORDCHAN. Короче, годится для всего, поскольку свойства эти общие:

handle - хэндл канала (см. 2 строчки выше).

freq - частота в герцах. Если здесь -1, останется текущая.

volume - громкость - от 0 до 100. -1 оставляет дефолтовую.

pan - баланс - (-101) - текущий, (-100) - влево, 0 - центр, 100 - вправо.

8) function BASS_ChannelGetAttributes(handle: DWORD; var freq, volume: DWORD; var pan: Integer): BOOL;

Получает атрибуты канала. Переменные такие же, как и в предыдущей функции. Если не хочешь получать какое-нибудь свойство, ставь null.

9) function BASS_ChannelSetPosition(handle: DWORD; pos: QWORD): BOOL;

Сдвигает позицию проигрывания на pos вперед. А это самое pos имеет разные значения в зависимости от хэндла; например, для CDCHANNEL - это количество в миллисекундах, считая от начала трека, а для HSTREAM - позиция в байтах. Получить позицию можно, соответственно, с помощью функции BASS_ChannelGetPosition.

Куем форму

Напомню, что главное на сегодня - интерфейс. Как говорится, прогу встречают по фейcу, а провожают по контенту, а если ты притащишь кому-нибудь сверхфункциональное, но омерзительно выглядящее чудище, то его отправят в trash, даже не выяснив всех достоинств.

Бросай на форму 1 Edit, 1 TImage, 1 TrackBar, 6 Кнопок, 1 TListBox, 1 TLabel, 1 OpenDialog. Все это должно выглядеть так:

Раздадим свойства всем этим компонентам:

RadioButton1 - свойство Caption - "From File". Если он будет выбран, то играть будем файл.

RadioButton2 - свойство Caption - "From CD". А если он, то играем аудио-компакт, причем в плейлист будет выведен список треков. В роли плейлиста выступает TListBox.

Button'ы под номерами 1, 2, 3 получают Caption'ы, соответственно: "Play", "Stop" и "Pause".

Button4 - свойство Caption - "ADD". Эта кнопка будет добавлять файлы в плейлист.

Button5 - свойство Caption - "View info...". Выводит информацию о файле.

Button6 - свойство Caption - "RMove". Необходима для удаления файла из плейлиста.

Label1 - свойство Caption - "Volume:". Находящийся под ней TrackBar будет определять громкость.

TImage - сюда придется залить свои пламенные поздравления. Все-таки подарок :).

Кодинг

Инициализация должна быть в OnCreate для формы. Вот и набивай туда следующее:

Здесь я инициализирую стандартный звук: 44100 Гц, стерео, 16 бит, устройство по умолчанию и проверяю версию bass.dll. Если она не 1.8, значит, ничего и не загружено. Поэтому аварийный выход через HALT. Вот, собственно, и вся инициализация. Теперь создай для RadioButton2 событие OnClick и пиши туда:

Если в CD-ROM'е имеется аудиодиск, то мы получаем список его треков и выводим его в плейлист в виде "Track XX". Если диска нет, то сообщаем об этом. Теперь давай сделаем две процедуры: StremPlay и PlayDisk. Для этого запиши их в конец раздела Type (который выше private):

procedure PlayDisk (NK: integer); //NK-номер трека

procedure PlayStrem (Name: string); //Name- имя файла

и нажми Ctrl-Shift-C. Дельфи сам создаст все нужное, тебе надо только вдолбить текст в появившиеся заготовки. Вот и вдалбливай. В PlayDisk:

Bass_CdPlay (NK, false, true);

А в PlayStrem - чуть сложнее:

f := PChar(Name);

result:= BASS_StreamCreateFile(FALSE, f, 0, 0, BASS_MP3_SETPOS);

IF result<>0 then BASS_StreamPlay(result, FALSE, 0);

Чтобы этот код заработал, в private надо объявить:

result: HStream;

f: PCHar;

Здесь я ничего объяснять не буду, т.к. ты читал теорию. Значит, уже все знаешь, поэтому идем дальше. Давай создадим для ListBox1 событие OnDblClick и сделаем так, чтобы двойной клик на какой-нибудь песне запускал ее воспроизведение. Do it:

Edit1.Text:= ListBox1.Items[ListBox1.ItemIndex];

IF RadioButton1.Checked then PlayStrem (Edit1.Text) else

PlayDisk (ListBox1.ItemIndex+1);

Здесь я передаю имя в Edit1, а затем играю трек или файл, в зависимости от желания пользователя. Заметь, что строки в ListBox нумеруются с 0, а треки - с 1. Отсюда и берется конструкция "+1".

Управление плеером

Кнопка "ADD" будет добавлять файл музона в плейлист. Именно файл, потому что треки, как ты помнишь, добавляются автоматически. Пишем онклик:

IF (RadioButton1.Checked) and (opendialog1.Execute) then

ListBox1.Items.Add(OpenDialog1.FileName);

Кнопка же "RMOVE" будет удалять выделенную позицию из плейлиста, поэтому ничего, кроме:

ListBox1.Items.Delete(ListBox1.ItemIndex);

она не заслуживает, а мы займемся самым основным: кнопками "Play", "Stop", "Pause" и трекбаром (он будет менять громкость). Онклик для "Play" ты напишешь сам, он почти аналогичен OnDblClick для плейлиста, а вот в "Pause" заливай этот код:

Здесь я сделал такую зависимость: если caption равно pause, значит музон уже играет и его можно стопить; если же он равен "Resume", значит он на паузе и можно делать resume. Если честно, этот способ нравится не всем, некоторые кодеры любят пользоваться глобальными булевыми переменными (true - играет, false - на паузе).

Взгляни теперь на онклик кнопки "STOP":

IF radiobutton1.Checked then Bass_channelstop (result) else

Bass_channelstop (CDCHANNEL);

Здесь все элементарно, главное - выбрать, что же нам надо остановить.

Ну и напоследок, создай для TrackBar событие OnChange и вбей туда:

bass_channelsetattributes (result,-1,trackbar1.Position,-1);

А минимальные и максимальные значения для него должны быть 0 и 100 соответственно. Логика проста - когда юзер начинает дергать за трекбар, громкость меняется, и это отображается в положении бегунка.

Вот и все, что я хотел рассказать. Онклик для кнопки "View info" ты посмотришь в исходнике на диске. Он откомментированный и предельно ясный. Тебе остается его как следует отмодернизировать. А вообще-то мы уже сделали большое дело, за которое не берутся даже злые пираты :). Ведь для своих коллекций mp3 они пишут простенькие оболочки, нагло эксплуатирующие тот самый WinAMP.

Pars Terminalis

Если ты сделал какой-нибудь мегаподарочный интерфейс, не скрывай его от общественности. Лучше вооружись электронной почтой и пришли его мне на alexander@real.xakep.ru. Если тебе жалко исходника - пришли бинарник. На худой конец скрин в формате BMP или нерабочий интерфейс. Самые кульные творения мы выложим на xakep.ru, пусть народ смотрит и учится. Только не забудь как следует запаковать свое добро RAR'ом - пожалей мой старенький модем :). Удачного тебе музона!

Листинг procedure TForm1.FormCreate

procedure TForm1.FormCreate(Sender: TObject);

begin

if BASS_GetVersion() <> MAKELONG(1,8) then begin

ShowMessage('BASS 1.8 не загружен!');

Halt; //Никогда так не делай. Это моветон :)

end;

// Инициализируем цифровой саунд -

// дефолт девайс, 44100 Гц, стерео, 16 бит

if not BASS_Init(-1, 44100, 0, handle) then

ShowMessage('Не могу инициализировать звук!');

// Инициализируем компакт

if not BASS_CDInit(nil, BASS_DEVICE_LEAVEVOL) then

ShowMessage('Не могу инициализировать компакт!');

// звуковой выход

BASS_Start;

end;

Обработчик OnClick для RadioButton2

procedure TForm1.RadioButton2Click(Sender: TObject);

var i: integer;

begin

If BASS_CDInDrive then

begin

RadioButton1.Checked;

For i:=1 to BASS_CDGetTracks do

begin

IF BASS_CDGetTracks>=10 then ListBox1.Items.Add('Track '+Inttostr(i)) else

ListBox1.Items.Add('Track 0'+Inttostr(i));

end;

end else

begin

ShowMessage ('Нет CD в дисководе! Че играть-то?');

RadioButton1.Checked:= true;

end;

end;

Онклик для кнопки: "PAUSE":

procedure TForm1.Button3Click(Sender: TObject);

begin

IF button3.Caption= 'Pause' then

begin

IF RadioButton2.Checked then

bass_channelpause (CDCHANNEL) else

bass_channelpause (result);

Button3.Caption:= 'Resume';

end else

begin

IF RadioButton2.Checked then

bass_channelresume (CDCHANNEL) else

bass_channelresume (result);

Button3.Caption:= 'Pause';

end;

end;

Источник http://www.realcoding.net/

 
Разместил 31/01/2004 от rolcom ( Прочитано: )

  blocks.gif
Связанные ссылки
 

· Больше про Работа со звуком и видео
· Новость от rolcom


Самая читаемая статья: Работа со звуком и видео:
Direct Show и Delphi

 
blocks.gif
Рейтинг статьи
 

Средняя оценка: 4.33
Ответов: 12


Пожалуйста, проголосуйте за эту статью:

Отлично
Очень хорошо
Хорошо
Нормально
Плохо


 
blocks.gif
опции
 


 Напечатать текущую страницу  Напечатать текущую страницу

 Отправить статью другу  Отправить статью другу

 
 

Page generation 0.068 seconds