Параллельно с Direct3D9 я делал библиотеку типов и модуль с вспомогательными функциями для DirectSound. В архиве библиотека типов dsvb.tlb и модуль DS_Functions.bas. В дальнейшем добавлю модуль класса для поддержки асинхронных уведомлений, пока можно пользоваться этим. После компиляции никаких зависимостей не остается (ну естественно нужен установленный DirectX).
В модуле DS_Functions содержатся следующие функции:
- DSCreateSoundBufferFromFile - создает объект с интерфейсом IDirectSoundBuffer8 из файла. Поддерживаются только WAVE и MP3 файлы. MP3 файлы могут содержать только ID3v1 и ID3v2 теги, какие-либо другие возможно не распознаются/не будут работать. Слишком длинные (по времени) файлы не поддерживаются. Для потокового воспроизведения нужно писать потоковое декодирование на основе кода функции DSCreateSoundBufferFromMemory. Для MP3 файлов используется конвертирование в WAV, а затем заполнение буфера PCM данными, используя ACM.
- DSCreateSoundBufferFromMemory - тоже самое, но вместо файла передается указатель на данные файла в памяти и их размер.
Также в архиве содержится пример WAVE/MP3 плеера который реализует некоторые методы IDirectSoundBuffer8 интерфейса (громкость, панорама, частота, эффекты).
TLB также особо сильно не тестировалась, поэтому что-то может не работать.
Разобрался Точнее Mikle помог разобраться).
Я просто думал, что lpFmt - это указатель на данные.
Привет. Для конкурса 32К начал урезать все, что можно. Но есть косяк. В P-коде вылетает, причем если добавить одну неиспользуемую переменную, то все ок.
Переменная reserved в процедуре DSCreateSoundBufferFromMemory. Если её убираю - все крашится.
Сможешь посмотреть?
Так урезал, т.к. поинтеры и размер буфера всегда на одни и теже числа смещаются.
https://yadi.sk/d/baG7qf-co9S6Y
В Оригинальная убрал обработку mp3, чтобы в окно влазла).
AWPStar
Нет, там действительно была ошибка, и в моем модуле тоже, спасибо за тестирование.
Нужно в DSCreateSoundBufferFromMemory, где я передавал 0 передавать 0&, иначе функция считает что это Integer (2 байта). Когда ты передавал reserved то функция писала оставшиеся 2 байта в первую половину reserved, а когда убирал переменная ptr частично затиралась. Так что просто нужно передавать 0&.
На самом деле так не нужно создавать так создавать буфер через временный файл - пиши данные сразу:
Option Explicit Private Declare Function memcpy Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long) As Long Public Type WAVEFORMATEX wFormatTag As Integer nChannels As Integer nSamplesPerSec As Long nAvgBytesPerSec As Long nBlockAlign As Integer wBitsPerSample As Integer cbSize As Integer End Type Function GetSound(ByVal ds As DirectSound8, b() As Byte) As IDirectSoundBuffer Dim bd As DSBUFFERDESC Dim wf As WAVEFORMATEX Dim ptr As Long Dim cb As Long ' // Set format wf.wFormatTag = 1 wf.wBitsPerSample = 8 wf.nSamplesPerSec = 44100 wf.nChannels = 1 wf.nBlockAlign = (wf.wBitsPerSample \ 8) * wf.nChannels wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign ' // Set buffer descriptor bd.dwFlags = DSBCAPS_CTRLVOLUME Or DSBCAPS_CTRLPAN Or DSBCAPS_CTRLFREQUENCY Or DSBCAPS_CTRLFX bd.dwSize = Len(bd) bd.lpwfxFormat = VarPtr(wf) bd.dwBufferBytes = UBound(b) + 1 ' // Create buffer ds.CreateSoundBuffer bd, GetSound, ByVal 0& ' // Lock buffer GetSound.Lock 0, 0, ptr, cb, 0&, 0&, DSBLOCK_ENTIREBUFFER ' // Copy audio data memcpy ByVal ptr, b(0), cb ' // Unlock buffer GetSound.Unlock ptr, cb, 0&, 0& End Function
Это намного быстрее и короче. API объяви в tlb, чтобы они меньше места занимали и быстрее работали.
Не совсем по теме. Сделал тут небольшй(совсем) движек.
https://yadi.sk/d/rcWIJlnQuYycR
Компилировал на FreeBasic. Исходники в архиве.
Правда надо бы константы добавить, но они стандартные.
Тема в архиве.