DirectMusic
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.216.43] |
|
|
MSDN Library
FAQ раздела
Поиск по разделу
Как правильно задавать вопросы
DirectMusic
|
Сообщ.
#1
,
|
|
|
|
Доброго времени суток
![]() Вобщем, задался я проблеммой проиграть MIDI из ресурса. Покурив достаточное время MSDN понял, что ничем другим, кроме как с помощью DirectMusic этого добиться вряд ли удасться, т.к. только он позволяет проигрывать музыку из памяти, а не из файла. Помучав Делфу я понял, что такого COM-сервиса как DirectMusic или чего-то вроде просто нету и тут явно нужно что-нибудь другое. Я слышал, что для Делфы переведёны заголовки (кажется DelphiX или как-то так, уже не помню - слышал об этом давно и краем уха), но у меня их, исессна, нет... Синшные примеры я немного разобрал, но не уверен, что готов воплотить их на делфе... Вобщем, мож кто знает, где взять эти заголовки DirectX и простенький примерчик проигрывания MIDI (даже можно и не из ресурса, это я и сам смогу) через DirectMusic... |
|
Сообщ.
#2
,
|
|
|
|
|
Сообщ.
#3
,
|
|
|
|
Arazel, не работает оно у меня...
Кроме того, это назвать "простеньким примером" никак нельзя... Зато я узнал, что можно проиграть файл с помощью модуля MMSystem, жаль только не понял как - слишком запутаны у сорцы, и не до конца уверен, что этот файл можно прочесть из ресурса... |
|
Сообщ.
#4
,
|
|
|
|
Ну вообщето ПРИМЕР работает и он классный!
![]() Второе про MIDI пройгрование я много видел примеров Например: ![]() ![]() uses MMSystem; // Play Midi procedure TForm1.Button1Click; const FileName = 'C:\YourFile.mid'; begin MCISendString(PChar('play ' + FileName), nil, 0, 0); end; // Stop Midi procedure TForm1.Button1Click; const FileName = 'C:\YourFile.mid'; begin MCISendString(PChar('stop ' + FileName), nil, 0, 0); end; А нащет ресурсов тоже дофига вот тоже пример: ![]() ![]() PlaySound('S1', HInstance, SND_RESOURCE or SND_ASYNC); просто у меня в Архиве много примеров, но на это надо время... |
|
Сообщ.
#5
,
|
|
|
|
Arazel, а ты понял, что написал ввиду того, что я просил совсем другое?
|
|
Сообщ.
#6
,
|
|
|
|
--= Eagle =--
Наверное я береборщил... |
|
Сообщ.
#7
,
|
|
|
|
--= Eagle =--, глянь тут: Как втиснуть в файл ресурсов (сообщение #343809)
|
|
Сообщ.
#8
,
|
|
|
|
Krid, там написана ахинея... MIDI-файл НЕ может быть проигран с помощью PlaySound() или sndPlaySound() !!
Кстати, могу сказать, что ![]() ![]() PlaySound('MYWAV' , 0, SND_RESOURCE); срабатывает не всегда, у меня на D7 не работает. А вот если указать поинтер на ресурс, то будет ОК... |
|
Сообщ.
#9
,
|
|
|
|
--= Eagle =--, звиняй - не ту ссылку дал (с копипастом промахнулся)
На самом деле хотел вот эту: Воспроизведение Mid файлов из ресурса (сообщение #639315)Сам на Delphi перекинешь? |
|
Сообщ.
#10
,
|
|
|
|
Krid, см. мой первй пост. У меня нет соответствующих заголовков DirectX для работы с DirectMusic. Если можешь всё устроить - я тебе буду премного балгодарен.
|
|
Сообщ.
#12
,
|
|
|
|
Krid, я не пишу на Си, ибо я его слишком плохо понимаю, и не очень он мне нравится...
|
|
Сообщ.
#13
,
|
|
|
|
--= Eagle =--, посмотри заголовки тут: DirectX headers and libraries
|
|
Сообщ.
#14
,
|
|
|
|
Krid, спасибо, это то, что я, собственно, и искал. Вот, перевёл пример, написанный CBP (спасибо ему огромное) с Сишки на Делфи, вот что получилось (немного исправленный код, музыку проигрывает - что уже радует):
![]() ![]() {$APPTYPE GUI} uses Windows, ActiveX, DirectMusic, DirectSound; var g_pLoader: IDirectMusicLoader = nil; g_pPerformance: IDirectMusicPerformance = nil; g_pSegment: IDirectMusicSegment = nil; _IDM: IDirectMusic; _IDS: IDirectSound; desc: DMUS_OBJECTDESC; hResource: THandle; {$R mymusic.RES} { --- mymusic.rc --- 12345 RCDATA "GIMN2.MID" } begin CoInitialize(nil); CoCreateInstance(CLSID_DirectMusicLoader, nil, CLSCTX_INPROC, IID_IDirectMusicLoader, g_pLoader); CoCreateInstance(CLSID_DirectMusicPerformance, nil, CLSCTX_INPROC, IID_IDirectMusicPerformance, g_pPerformance); hResource := FindResource(hInstance, MAKEINTRESOURCE(12345), RT_RCDATA); g_pPerformance.Init(_IDM, _IDS, 0); g_pPerformance.AddPort(nil); desc.dwSize := SizeOf(DMUS_OBJECTDESC); desc.pbMemData := LockResource(LoadResource(Hinstance, FindResource(hInstance, MAKEINTRESOURCE(12345), RT_RCDATA))); desc.llMemLength := SizeofResource(hInstance, hResource); desc.guidClass := CLSID_DirectMusicSegment; desc.dwValidData := DMUS_OBJ_CLASS or DMUS_OBJ_MEMORY; g_pLoader.GetObject(desc, IID_IDirectMusicSegment, g_pSegment); g_pSegment.SetParam(GUID_Enable_Auto_Download, Cardinal(-1), 0, 0, @g_pPerformance); g_pPerformance.PlaySegment(g_pSegment, 0, 0, nil); MessageBox(0, 'Click OK to Stop.', 'Playing MIDI...', MB_OK); g_pPerformance.Stop(g_pSegment, nil, 0, 0); g_pPerformance.CloseDown; //в сравнении с сишными заголовками, //в делфовых аналогах нет таких процедур: //g_pLoader.Release //g_pPerformance.Release; //g_pSegment.Release; //есть только g_pLoader.ReleaseObject(nil); CoUninitialize; end. Огорчает одна вещь - иногда ни с того, ни с сего появляются сообщения Runtime error 216 at 00403430... Но там нужно отлаживать код на ассемблере, адрес находится за пределами главной процедуры ( в сишке это называлось бы функция main() )... И ещё одно: никто случаем не знает, как загрузить инструменты из оригинального MIDI, а то там наверное используются инструменты по-умолчанию, ибо звучание немного не то (по сравнению с большинством моедаплееров)? В MSDN'е я вычилал, что нужно ещё добавить строку типа ![]() ![]() g_pSegment.SetParam(GUID_StandardMIDIFile, Cardinal(-1), 0, 0, @g_pPerformance); тогда инструменты должнызагрузиться... Чё-то не фурычит ![]() Вобщем, я всё ещё не отказался бы от помощи |
|
Сообщ.
#15
,
|
|
|
|
Только что нашёл. Вот это:
Цитата --= Eagle =--, 15.03.2006, 15:47:27, 1044742 //в сравнении с сишными заголовками, //в делфовых аналогах нет таких процедур: //g_pLoader.Release //g_pPerformance.Release; //g_pSegment.Release; //есть только g_pLoader.ReleaseObject(nil); заменяем на: ![]() ![]() g_pLoader._Release; g_pPerformance._Release; g_pSegment._Release; Правда, это ничего не меняет... Видать, ошибка где-то ещё... Вобщем, пойду покурю ещё разок MSDN... |
|
Сообщ.
#16
,
|
|
|
|
Благодаря CBP добавил код для отключения эффекта реверберации, но всё равно звучание не такое, как надо...
Runtime error всё ещё вылезает... ![]() ![]() ![]() {$APPTYPE GUI} uses Windows, ActiveX, DirectMusic; var g_pLoader: IDirectMusicLoader = nil; g_pPerformance: IDirectMusicPerformance = nil; g_pSegment: IDirectMusicSegment = nil; g_pDirectMusic: IDirectMusic = nil; g_pPort: IDirectMusicPort = nil; desc: DMUS_OBJECTDESC; portparams: DMUS_PORTPARAMS; // для отключения реверберации hResource: THandle; {$R mymusic.RES} { --- mymusic.rc --- 12345 RCDATA "GIMN2.MID" } begin CoInitialize(nil); CoCreateInstance(CLSID_DirectMusicLoader, nil, CLSCTX_INPROC, IID_IDirectMusicLoader, g_pLoader); CoCreateInstance(CLSID_DirectMusicPerformance, nil, CLSCTX_INPROC, IID_IDirectMusicPerformance, g_pPerformance); hResource := FindResource(hInstance, MAKEINTRESOURCE(12345), RT_RCDATA); g_pPerformance.Init(g_pDirectMusic, nil, 0); desc.dwSize := SizeOf(DMUS_OBJECTDESC); desc.pbMemData := LockResource(LoadResource(Hinstance, FindResource(hInstance, MAKEINTRESOURCE(12345), RT_RCDATA))); desc.llMemLength := SizeofResource(hInstance, hResource); desc.guidClass := CLSID_DirectMusicSegment; desc.dwValidData := DMUS_OBJ_CLASS or DMUS_OBJ_MEMORY; // не отключать реверберацию: // g_pPerformance.AddPort(nil); //{ --- отключить реверберацию ---> portparams.dwSize := SizeOf(DMUS_PORTPARAMS); portparams.dwValidParams := DMUS_PORTPARAMS_SAMPLERATE or DMUS_PORTPARAMS_EFFECTS; portparams.dwSampleRate := 22050; portparams.dwEffectFlags := DMUS_EFFECT_NONE; g_pDirectMusic.CreatePort(GUID_NULL, portparams, g_pPort, nil); g_pPort.Activate(TRUE); g_pPerformance.AddPort(g_pPort); g_pPerformance.AssignPChannelBlock(0, g_pPort, 1); // <-------------------------------} g_pLoader.GetObject(desc, IID_IDirectMusicSegment, g_pSegment); g_pSegment.SetParam(GUID_StandardMIDIFile, Cardinal(-1), 0, 0, @g_pPerformance); g_pSegment.SetParam(GUID_Enable_Auto_Download, Cardinal(-1), 0, 0, @g_pPerformance); // g_pPerformance.DownloadInstrument( ??? ) g_pPerformance.PlaySegment(g_pSegment, 0, 0, nil); MessageBox(0, 'Click OK to Stop.', 'Playing MIDI...', MB_OK); g_pPerformance.Stop(g_pSegment, nil, 0, 0); g_pPerformance.CloseDown; g_pLoader._Release; g_pPerformance._Release; g_pSegment._Release; //{ --- если реверберация отключена ---> g_pDirectMusic._Release; g_pPort._Release; // <-------------------------------} CoUninitialize; end. |
|
Сообщ.
#17
,
|
|
|
|
Кто не будь выложите модуль DirectMusic
|
|
Сообщ.
#18
,
|
|
|
|
Arazel, см. пост #13.
|
|
Сообщ.
#19
,
|
|
|
|
По поводу Runtime error'ов: ошибка найдена и учтена на будущее
Цитата ekamaloff, 17.03.06, 9:43:00 Дело в том, что с указателями на интерфейс Delphi работает особенным образом. В частности при выходе из блока (процедуры, функции, программы) для всех локальных переменных такого типа, вызывается системная функция _IntfClear. Она проверяет переданный ей указатель на nil и, при необходимости, производит уменьшение счетчика ссылок. В твоем случае это и происходило. Причем происходило уже после того, как из памяти был выгружен DirectX и сам COM. Вследствие этого возникала ошибка. Когда мы все вызовы IInterface._Release заменяем на присвоение nil (кстати это также приводит к автоматическому вызову _Release), то при выходе из блока, _Release на этом указателе уже не вызывается, поскольку он нулевой. И все в итоге получается тип-топ. Вобщем, _Release убираем, делаем так: ![]() ![]() g_pLoader := nil; g_pPerformance := nil; g_pSegment := nil; //{ --- если реверберация отключена ---> g_pDirectMusic := nil; g_pPort := nil; // <-------------------------------} |
|
Сообщ.
#20
,
|
|
|
|
И чем это все закончилось
|
|
Сообщ.
#21
,
|
|
|
|
Цитата Arazel, 17.03.2006, 20:54:39, 1047486 И чем это все закончилось Тем, что код, в принципе, рабочий. CBP говорит, что у него MIDI вопроизводится без искажений, у меня - с искажениями. Моя звуковуха - SBLive! 5.1, какая у него - не знаю... У меня есть идея, что, возможно, нужно проигрывать на другое звуковое устройство, если их несколько установлено... Или загружать инструменты, только как? ХЗ... Хотел бы, чтобы мне помогли советом, да потестили... |
|
Сообщ.
#22
,
|
|
|
|
--= Eagle =-- Ну попробуй WinAMP(ом) пройграть
или тем же PianoEx.rar Если есть искажение тогда Зкукавуха иначе код |
|
Сообщ.
#23
,
|
|
|
|
Цитата Arazel @ Если есть искажение тогда Зкукавуха Да нифига подобного - у меня и в винампе (да и везде) играет нормально, а код CBP выдает совсем другой звук. Так что, имхо, тут дело не в звуковухе, а в настройке инструментов. |
|
Сообщ.
#24
,
|
|
|
|
Arazel, ты меня конечно извини, но ты ВНИМАТЕЛЬНО ВЧИТЫВАЕШЬСЯ В СООБЩЕНИЯ?! МОЯ ПРОГРАММА на МОЕЙ МАШИНЕ воспроизводит MIDI С ИСКАЖЕНИЯМИ, на МАШИНЕ CBP ЭТА ЖЕ ПРОГРАММА воспроизводит ТОТ ЖЕ MIDI БЕЗ ИСКАЖЕНИЙ. Сейчас я хочу узнать почему это происходит и сделать так, чтобы и на моей машине моя программа не искажала мидяху.
|
|
Сообщ.
#25
,
|
|
|
|
Krid
--= Eagle =-- Не знаю, только что запустил, что в Winapm(е) что в JetAudio а также MediaPlayer везде нормально играет |