Параллельно с 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. Исходники в архиве.
Правда надо бы константы добавить, но они стандартные.
Тема в архиве.