Господа! Я что-то не понимаю, как средствами MFAPI создать WAV-файл. Пробую вот так: Код (Text): // test_mfapi.cpp : This file contains the 'main' function. Program execution begins and ends there. // #include <shtypes.h> #include <shlwapi.h> #include <propvarutil.h> #include <guiddef.h> #include <propidl.h> #include <propvarutil.h> #include <mfapi.h> #include <mfidl.h> #include <mferror.h> #include <mfreadwrite.h> int main() { // Create SinkWriter HRESULT hr; IMFSinkWriter* pSinkWriter = NULL; const WCHAR* wpath = L"test.wav"; // Initialize the COM runtime. hr = ::CoInitializeEx(0, COINIT_MULTITHREADED); if (SUCCEEDED(hr)) { // Initialize the Media Foundation platform. ::MFStartup(MF_VERSION); } // Create attributes IMFAttributes* pAttributes = NULL; hr = ::MFCreateAttributes(&pAttributes, 16); if (!SUCCEEDED(hr)) return -1; if (SUCCEEDED(hr)) hr = pAttributes->SetGUID(MF_TRANSCODE_CONTAINERTYPE, MFTranscodeContainerType_WAVE); if (!SUCCEEDED(hr)) { pAttributes->Release(); return -1; } // Create sink writer hr = ::MFCreateSinkWriterFromURL(wpath, NULL, pAttributes, &pSinkWriter); pAttributes->Release(); if (!SUCCEEDED(hr)) return -1; return 0; } Функция ::MFCreateSinkWriterFromURL создаёт пустой файл и возвращает ошибку 0xc00d36fa = MF_E_CANNOT_CREATE_SINK. Что я делаю не так? --- Сообщение объединено, 7 апр 2019 --- Кажись, понял MFTranscodeContainerType_WAVE WAVE file container. Supported in Windows 8.1 and and later. --- Сообщение объединено, 7 апр 2019 --- Wikipedia: 2007 - 1991= 16 лет. Microsoft, вы серьёзно?
В семплах на майкрософт.ком просто создается интерфейс IMFSinkWriter Код (Text): HRESULT hr = MFCreateSinkWriterFromURL(L"output.wmv", NULL, NULL, &pSinkWriter); А уже потом ему устанавливаются атрибуты.
*.wmv создаётся без проблем, а вот *.wav - вылетает ошибка. А мне нужно писать в WAV, PCM, float32. --- Сообщение объединено, 8 апр 2019 --- Thetrik посмотрел описание функций, ОК, попробую. Но не интегрировать в омегафреймворк поддержку RIFF с самого начала - это верх долбодятлизма.
Да я уже весь код необходимый написал по туториалам и сэмплам. Проблема в том, что я тестирую на Windows 7 всё это дело, а там запись WAV-файлов тупо не поддерживается.
Стало интересно, а что дает применение средств MFAPI? Я когда с созданием WAV-файлов эксперементировал, то пользовался mmio функциями. Правда это было на Win XP.
Ну вы можете делать кодирование/декодирование налету в указанный вами формат. То есть, если вашей приложухе нужно грузить аудиофайлы, то через mfapi вы автоматом сможете грузить не только WAV. То же касается и экспорта.
Лол. По теме: WAV и BMP - это два настолько простых формата, что имхо нет ничего зазорного в том, чтобы прописать их хексом прямо в коде, типа unsigned char header[] = {...}; Конечно, сам этот массив копипастить не нужно - его нужно засунуть в класс или функцию, но думаю это и так понятно.
_DEN_, сразу чувствуется, что вы не музыкант и далеки от музыкального программирования. SadKo, ловите сразу Дена на слове - вдруг, действительно, чем-то дельным поможет. Мне же вон с интерполяцией помог. Может и вам поможет.
Если я правильно понял, то тут можно использовать ACM - будет работать и на XP. Вот, мб пригодится, код с созданием WAVE файла + чанки с информацией: Код (Visual Basic): Public Const ARTIST_NAME As String = "TrickComposer_1.4" Public Const GENRE_NAME As String = "8 bit" Public Function ExportToWave( _ ByVal curSong As Song, _ ByRef fileName As String) As Boolean Dim Ret As Long Dim hWave As Long Dim chkRIFF As MMCKINFO Dim chkData As MMCKINFO Dim chkList As MMCKINFO Dim chkSub As MMCKINFO Dim dstFormat As WAVEFORMATEX Dim buffer() As Integer Dim Year As String SetProgressState frmMain, TBPF_NORMAL curSong.SetPos 0 dstFormat.wFormatTag = 1 dstFormat.wBitsPerSample = 16 dstFormat.nSamplesPerSec = curSong.SampleRate dstFormat.nChannels = 2 dstFormat.nBlockAlign = (dstFormat.wBitsPerSample \ 8) * dstFormat.nChannels dstFormat.nAvgBytesPerSec = dstFormat.nBlockAlign * dstFormat.nSamplesPerSec If Len(Dir$(fileName)) Then Kill fileName ' // Create wave file hWave = mmioOpen(fileName, ByVal 0&, MMIO_WRITE Or MMIO_CREATE) If hWave = 0 Then MsgBox "Error creating wave file" GoTo ExitExport End If ' // Create RIFF-WAVE chunk chkRIFF.fccType = mmioStringToFOURCC("WAVE", 0) If mmioCreateChunk(hWave, chkRIFF, MMIO_CREATERIFF) Then mmioClose hWave MsgBox "Error creating RIFF-WAVE chunk" GoTo ExitExport End If ' // Create fmt chunk chkData.ckid = mmioStringToFOURCC("fmt", 0) If mmioCreateChunk(hWave, chkData, 0) Then mmioClose hWave MsgBox "Error creating fmt chunk" GoTo ExitExport End If ' // Write format If mmioWrite(hWave, dstFormat, Len(dstFormat)) = -1 Then mmioClose hWave MsgBox "Error writing format" GoTo ExitExport End If ' // Update fmt-chunk size mmioAscend hWave, chkData, 0 ' // Create data chunk chkData.ckid = mmioStringToFOURCC("data", 0) If mmioCreateChunk(hWave, chkData, 0) Then mmioClose hWave MsgBox "Error creating data chunk" GoTo ExitExport End If ReDim buffer(12000 - 1) ' // Write pause If mmioWrite(hWave, buffer(0), (UBound(buffer) + 1) * Len(buffer(0))) = -1 Then mmioClose hWave MsgBox "Error writing data" GoTo ExitExport End If Do While curSong.GetPos <= curSong.SongDuration DoEvents curSong.Play buffer() ' // Write data If mmioWrite(hWave, buffer(0), (UBound(buffer) + 1) * Len(buffer(0))) = -1 Then mmioClose hWave MsgBox "Error writing data" GoTo ExitExport End If ZeroMemory buffer(0), (UBound(buffer) + 1) * Len(buffer(0)) SetProgressValue frmMain, curSong.GetPos() / curSong.SongDuration() 'frmMain.picProgress.Line (0, 0)-(curSong.GetPos(), 1), vbRed, BF Loop ' // Update data-chunk size mmioAscend hWave, chkData, 0 ' // Create LIST chunk chkList.fccType = mmioStringToFOURCC("INFO", 0) If mmioCreateChunk(hWave, chkList, MMIO_CREATELIST) Then mmioClose hWave MsgBox "Error creating LIST-INFO chunk" GoTo ExitExport End If ' // Create IART chunk chkSub.ckid = mmioStringToFOURCC("IART", 0) If mmioCreateChunk(hWave, chkSub, 0) Then mmioClose hWave MsgBox "Error creating IART chunk" GoTo ExitExport End If ' // Write IART If mmioWrite(hWave, ByVal StrPtr(StrConv(ARTIST_NAME, vbFromUnicode)), Len(ARTIST_NAME)) = -1 Then mmioClose hWave MsgBox "Error writing IART" GoTo ExitExport End If ' // Update IART-chunk size mmioAscend hWave, chkSub, 0 Year = CStr(DateTime.Year(Now)) ' // Create ICRD chunk chkSub.ckid = mmioStringToFOURCC("ICRD", 0) If mmioCreateChunk(hWave, chkSub, 0) Then mmioClose hWave MsgBox "Error creating ICRD chunk" GoTo ExitExport End If ' // Write ICRD If mmioWrite(hWave, ByVal StrPtr(StrConv(Year, vbFromUnicode)), Len(Year)) = -1 Then mmioClose hWave MsgBox "Error writing ICRD" GoTo ExitExport End If ' // Update ICRD-chunk size mmioAscend hWave, chkSub, 0 ' // Create IGNR chunk chkSub.ckid = mmioStringToFOURCC("IGNR", 0) If mmioCreateChunk(hWave, chkSub, 0) Then mmioClose hWave MsgBox "Error creating IGNR chunk" GoTo ExitExport End If ' // Write IGNR If mmioWrite(hWave, ByVal StrPtr(StrConv(GENRE_NAME, vbFromUnicode)), Len(GENRE_NAME)) = -1 Then mmioClose hWave MsgBox "Error writing IGNR" GoTo ExitExport End If ' // Update IGNR-chunk size mmioAscend hWave, chkSub, 0 ' // Create INAM chunk chkSub.ckid = mmioStringToFOURCC("INAM", 0) If mmioCreateChunk(hWave, chkSub, 0) Then mmioClose hWave MsgBox "Error creating INAM chunk" GoTo ExitExport End If ' // Write INAM If mmioWrite(hWave, ByVal StrPtr(StrConv(curSong.Name, vbFromUnicode)), Len(curSong.Name)) = -1 Then mmioClose hWave MsgBox "Error writing INAM" GoTo ExitExport End If ' // Update INAM-chunk size mmioAscend hWave, chkSub, 0 ' // Update LIST-chunk size mmioAscend hWave, chkList, 0 ' // Update RIFF-chunk size mmioAscend hWave, chkRIFF, 0 ExportToWave = True ExitExport: mmioClose hWave SetProgressState frmMain, TBPF_NOPROGRESS End Function В цикле просто извлекаются PCM данные и пишутся в файл.
Thetrik да нашёл уже сэмплы, разобрался Тыц: https://github.com/sadko4u/lsp-plug...2108cf0cf5/src/core/files/AudioFile.cpp#L1071 https://github.com/sadko4u/lsp-plug...2108cf0cf5/src/core/files/AudioFile.cpp#L1136 https://github.com/sadko4u/lsp-plug...2108cf0cf5/src/core/files/AudioFile.cpp#L1627 Теперь надо будет обратную задачу решать --- Сообщение объединено, 8 апр 2019 --- А есть какие-нибудь семплы по декодированию WAV при помощи ACM?
Есть на VB6. https://wasm.in/threads/vokoder-na-vb6.31874/ - тут класс декодирует из произволного WAV в необходимый PCM. Вот есть декодирование из MP3 в PCM (тоже VB6): Код (Visual Basic): Option Explicit Private Type OPENFILENAME lStructSize As Long hwndOwner As Long hInstance As Long lpstrFilter As Long lpstrCustomFilter As Long nMaxCustFilter As Long nFilterIndex As Long lpstrFile As Long nMaxFile As Long lpstrFileTitle As Long nMaxFileTitle As Long lpstrInitialDir As Long lpstrTitle As Long Flags As Long nFileOffset As Integer nFileExtension As Integer lpstrDefExt As Long lCustData As Long lpfnHook As Long lpTemplateName As Long End Type Private Type curBuffer b(15) As Currency End Type Private Type mp3Const bitrate(1, 15) As Integer smprate(2, 3) As Long End Type Private Type LARGE_INTEGER lowpart As Long highpart As Long End Type Private 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 Private Type MPEGLAYER3WAVEFORMAT wFormatTag As Integer nChannels As Integer nSamplesPerSec As Long nAvgBytesPerSec As Long nBlockAlign As Integer wBitsPerSample As Integer cbSize As Integer wID As Integer fdwFlags As Long nBlockSize As Integer nFramesPerBlock As Integer nCodecDelay As Integer End Type Private Type ACMSTREAMHEADER cbStruct As Long fdwStatus As Long lpdwUser As Long lppbSrc As Long cbSrcLength As Long cbSrcLengthUsed As Long lpdwSrcUser As Long lppbDst As Long cbDstLength As Long cbDstLengthUsed As Long lpdwDstUser As Long dwDriver(9) As Long End Type Private Type MMCKINFO ckid As Long ckSize As Long fccType As Long dwDataOffset As Long dwFlags As Long End Type Private Declare Function GetOpenFileName Lib "comdlg32.dll" _ Alias "GetOpenFileNameW" ( _ pOpenfilename As OPENFILENAME) As Long Private Declare Function GetSaveFileName Lib "comdlg32.dll" _ Alias "GetSaveFileNameW" ( _ pOpenfilename As OPENFILENAME) As Long Private Declare Function memcpy Lib "kernel32" _ Alias "RtlMoveMemory" ( _ ByRef Destination As Any, _ ByRef Source As Any, _ ByVal Length As Long) As Long Private Declare Function CreateFile Lib "kernel32" _ Alias "CreateFileW" ( _ ByVal lpFileName As Long, _ ByVal dwDesiredAccess As Long, _ ByVal dwShareMode As Long, _ lpSecurityAttributes As Any, _ ByVal dwCreationDisposition As Long, _ ByVal dwFlagsAndAttributes As Long, _ ByVal hTemplateFile As Long) As Long Private Declare Function CloseHandle Lib "kernel32" ( _ ByVal hObject As Long) As Long Private Declare Function CreateFileMapping Lib "kernel32" _ Alias "CreateFileMappingW" ( _ ByVal hFile As Long, _ lpFileMappingAttributes As Any, _ ByVal flProtect As Long, _ ByVal dwMaximumSizeHigh As Long, _ ByVal dwMaximumSizeLow As Long, _ ByVal lpName As Long) As Long Private Declare Function MapViewOfFile Lib "kernel32" ( _ ByVal hFileMappingObject As Long, _ ByVal dwDesiredAccess As Long, _ ByVal dwFileOffsetHigh As Long, _ ByVal dwFileOffsetLow As Long, _ ByVal dwNumberOfBytesToMap As Long) As Long Private Declare Function UnmapViewOfFile Lib "kernel32" ( _ ByVal lpBaseAddress As Long) As Long Private Declare Function GetMem4 Lib "msvbvm60" ( _ ByRef Src As Any, _ ByRef Dst As Any) As Long Private Declare Function GetMem8 Lib "msvbvm60" ( _ ByRef Src As Any, _ ByRef Dst As Any) As Long Private Declare Function IsBadReadPtr Lib "kernel32" ( _ ByRef lp As Any, _ ByVal ucb As Long) As Long Private Declare Function SetFilePointerEx Lib "kernel32" ( _ ByVal hFile As Long, _ ByVal liDistanceToMoveL As Long, _ ByVal liDistanceToMoveH As Long, _ ByRef lpNewFilePointer As LARGE_INTEGER, _ ByVal dwMoveMethod As Long) As Long Private Declare Function acmStreamClose Lib "msacm32" ( _ ByVal has As Long, _ ByVal fdwClose As Long) As Long Private Declare Function acmStreamConvert Lib "msacm32" ( _ ByVal has As Long, _ ByRef pash As ACMSTREAMHEADER, _ ByVal fdwConvert As Long) As Long Private Declare Function acmStreamMessage Lib "msacm32" ( _ ByVal has As Long, _ ByVal uMsg As Long, _ ByVal lParam1 As Long, _ ByVal lParam2 As Long) As Long Private Declare Function acmStreamOpen Lib "msacm32" ( _ ByRef phas As Any, _ ByVal had As Long, _ ByRef pwfxSrc As Any, _ ByRef pwfxDst As Any, _ ByRef pwfltr As Any, _ ByRef dwCallback As Any, _ ByRef dwInstance As Any, _ ByVal fdwOpen As Long) As Long Private Declare Function acmStreamPrepareHeader Lib "msacm32" ( _ ByVal has As Long, _ ByRef pash As ACMSTREAMHEADER, _ ByVal fdwPrepare As Long) As Long Private Declare Function acmStreamReset Lib "msacm32" ( _ ByVal has As Long, _ ByVal fdwReset As Long) As Long Private Declare Function acmStreamSize Lib "msacm32" ( _ ByVal has As Long, _ ByVal cbInput As Long, _ ByRef pdwOutputBytes As Long, _ ByVal fdwSize As Long) As Long Private Declare Function acmStreamUnprepareHeader Lib "msacm32" ( _ ByVal has As Long, _ ByRef pash As ACMSTREAMHEADER, _ ByVal fdwUnprepare As Long) As Long Private Declare Function mmioClose Lib "winmm.dll" ( _ ByVal hmmio As Long, _ Optional ByVal uFlags As Long) As Long Private Declare Function mmioOpen Lib "winmm.dll" _ Alias "mmioOpenW" ( _ ByVal szFileName As Long, _ ByRef lpmmioinfo As Any, _ ByVal dwOpenFlags As Long) As Long Private Declare Function mmioStringToFOURCC Lib "winmm.dll" _ Alias "mmioStringToFOURCCA" ( _ ByVal sz As String, _ ByVal uFlags As Long) As Long Private Declare Function mmioAscend Lib "winmm.dll" ( _ ByVal hmmio As Long, _ ByRef lpck As MMCKINFO, _ ByVal uFlags As Long) As Long Private Declare Function mmioCreateChunk Lib "winmm.dll" ( _ ByVal hmmio As Long, _ ByRef lpck As MMCKINFO, _ ByVal uFlags As Long) As Long Private Declare Function mmioWrite Lib "winmm.dll" ( _ ByVal hmmio As Long, _ ByRef pch As Any, _ ByVal cch As Long) As Long Private Const MMIO_CREATERIFF As Long = &H20 Private Const MMIO_DIRTY As Long = &H10000000 Private Const MMIO_CREATE As Long = &H1000 Private Const MMIO_WRITE As Long = &H1 Private Const OPEN_EXISTING As Long = 3 Private Const PAGE_READONLY As Long = 2& Private Const FILE_SHARE_READ As Long = &H1 Private Const INVALID_HANDLE_VALUE As Long = -1 Private Const GENERIC_READ As Long = &H80000000 Private Const FILE_MAP_READ As Long = &H4 Private Const FILE_ATTRIBUTE_NORMAL As Long = &H80 Private Const RIFF_SIGNATURE As Long = &H46464952 Private Const WAVE_SIGNATURE As Long = &H45564157 Private Const FMT_SIGNATURE As Long = &H20746D66 Private Const DATA_SIGNATURE As Long = &H61746164 Private Const FILE_END As Long = 2 Private Const ERROR_FILE_NOT_FOUND As Long = 2 Private Const MPEGLAYER3_FLAG_PADDING_OFF As Long = 2 Private Const WAVE_FORMAT_MPEGLAYER3 As Long = &H55 Private Const WAVE_FORMAT_PCM As Long = 1 Private Const MPEGLAYER3_WFX_EXTRA_BYTES As Long = 12 Private Const MPEGLAYER3_ID_MPEG As Long = 1 Private Const ACM_STREAMSIZEF_SOURCE As Long = &H0 Private Const ACM_STREAMCONVERTF_BLOCKALIGN As Long = &H4 Private Constants As mp3Const Private Sub cmdConvert_Click() Dim hFile As Long Dim hMap As Long Dim lpData As Long Dim errNum As Long Dim size As LARGE_INTEGER hFile = CreateFile(StrPtr(txtIn.Text), GENERIC_READ, FILE_SHARE_READ, ByVal 0&, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0) If hFile = INVALID_HANDLE_VALUE Then If Err.LastDllError = ERROR_FILE_NOT_FOUND Then MsgBox "Input file not found" Else MsgBox "Error occured" End If Exit Sub End If ' // Get file size SetFilePointerEx hFile, 0, 0, size, FILE_END If size.highpart <> 0 Or size.lowpart < 0 Then MsgBox "File too big" Exit Sub End If hMap = CreateFileMapping(hFile, ByVal 0&, PAGE_READONLY, 0, 0, 0) CloseHandle hFile If hMap = 0 Then MsgBox "Error mapping creation" Exit Sub End If lpData = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0) CloseHandle hMap If lpData = 0 Then MsgBox "Memory mapping error" Exit Sub End If If Not ConvertFromMemory(lpData, size.lowpart) Then MsgBox "Error during the conversion" End If UnmapViewOfFile lpData End Sub Private Function ConvertFromMemory( _ ByVal lpData As Long, _ ByVal szData As Long) As Boolean Dim hdr(9) As Byte Dim size As Long Dim ret As Long Dim szDat As Long Dim compl As Long Dim orSize As Long If IsBadReadPtr(ByVal lpData, szData) Then Exit Function If szData >= 128 Then ' // Skip ID3V1 tag memcpy hdr(0), ByVal lpData + szData - 128, 3 If hdr(0) = &H54 And hdr(1) = &H41 And hdr(2) = &H47 Then szData = szData - 128 End If End If If szData >= 10 Then ' // Skip ID3V2 tags from beginning memcpy hdr(0), ByVal lpData, 10 If hdr(0) = &H49 And hdr(1) = &H44 And hdr(2) = &H33 Then ' // Footer present If hdr(5) And &H10 Then szData = szData - 10 End If size = hdr(6) * &H200000 size = size Or (hdr(7) * &H4000&) size = size Or (hdr(8) * &H80&) size = size Or hdr(9) size = size + 10 lpData = lpData + size szData = szData - size Else ' // Skip ID3V2 tags from end memcpy hdr(0), ByVal lpData + szData - 10, 10 If hdr(2) = &H49 And hdr(1) = &H44 And hdr(0) = &H33 Then szData = szData - 10 size = hdr(6) * &H200000 size = size Or (hdr(7) * &H4000&) size = size Or (hdr(8) * &H80&) size = size Or hdr(9) size = size + 10 szData = szData - size End If End If End If If szData < 4 Then Exit Function ' // Find a frame sync Do GetMem4 ByVal lpData, hdr(0) If hdr(0) = &HFF And (hdr(1) And &HE0) = &HE0 Then Dim vers As Long Dim layer As Long Dim bitrate As Long Dim smprate As Long Dim padding As Long Dim channel As Long Dim format As MPEGLAYER3WAVEFORMAT vers = (hdr(1) And &H18) \ 8 If vers = 1 Then Exit Function layer = (hdr(1) And &H6) \ 2 If layer <> 1 Then Exit Function ' Only Layer 3 If vers = 3 Then bitrate = Constants.bitrate(0, (hdr(2) And &HF0) \ &H10) Else bitrate = Constants.bitrate(1, (hdr(2) And &HF0) \ &H10) End If If vers = 3 Then smprate = Constants.smprate(0, (hdr(2) And &HC) \ &H4) ElseIf vers = 2 Then smprate = Constants.smprate(1, (hdr(2) And &HC) \ &H4) Else smprate = Constants.smprate(2, (hdr(2) And &HC) \ &H4) End If padding = (hdr(2) And &H2) \ 2 channel = -(((hdr(3) And &HC0) \ 64) <> 3) + 1 If vers = 3 Then size = Int(144000 * bitrate / smprate) + padding Else size = Int(72000 * bitrate / smprate) + padding End If With format .wFormatTag = WAVE_FORMAT_MPEGLAYER3 .cbSize = MPEGLAYER3_WFX_EXTRA_BYTES .nChannels = channel .nAvgBytesPerSec = bitrate * 128 .wBitsPerSample = 0 .nBlockAlign = 1 .nSamplesPerSec = smprate .nFramesPerBlock = 1 .nCodecDelay = 0 .fdwFlags = MPEGLAYER3_FLAG_PADDING_OFF .wID = MPEGLAYER3_ID_MPEG .nBlockSize = size End With Exit Do End If lpData = lpData + 1 szData = szData - 1 Loop While szData >= 4 If szData > 0 And format.wFormatTag = WAVE_FORMAT_MPEGLAYER3 Then ' // Try to convert Dim hStream As Long Dim dstFormat As WAVEFORMATEX Dim buffer() As Byte Dim acmHdr As ACMSTREAMHEADER Dim outSize As Long Dim index As Long orSize = szData picProgress.Cls picProgress.Visible = True With dstFormat .cbSize = Len(dstFormat) .nChannels = format.nChannels .nSamplesPerSec = format.nSamplesPerSec .wBitsPerSample = 16 .nBlockAlign = (.wBitsPerSample \ 8) * .nChannels .nAvgBytesPerSec = .nBlockAlign * .nSamplesPerSec .wFormatTag = WAVE_FORMAT_PCM End With ' // Open conversion stream ret = acmStreamOpen(hStream, 0, format, dstFormat, ByVal 0&, ByVal 0&, ByVal 0&, 0) If ret Then Exit Function Dim hWave As Long Dim chkRIFF As MMCKINFO Dim chkData As MMCKINFO ' // Create wave file hWave = mmioOpen(StrPtr(txtOut.Text), ByVal 0, MMIO_WRITE Or MMIO_CREATE) If hWave = 0 Then acmStreamClose hStream, 0 MsgBox "Error creating wave file" Exit Function End If ' // Create RIFF-WAVE chunk chkRIFF.fccType = mmioStringToFOURCC("WAVE", 0) If mmioCreateChunk(hWave, chkRIFF, MMIO_CREATERIFF) Then acmStreamClose hStream, 0 mmioClose hWave MsgBox "Error creating RIFF-WAVE chunk" Exit Function End If ' // Create fmt chunk chkData.ckid = mmioStringToFOURCC("fmt", 0) If mmioCreateChunk(hWave, chkData, 0) Then acmStreamClose hStream, 0 mmioClose hWave MsgBox "Error creating fmt chunk" Exit Function End If ' // Write format If mmioWrite(hWave, dstFormat, Len(dstFormat)) = -1 Then acmStreamClose hStream, 0 mmioClose hWave MsgBox "Error writing format" Exit Function End If ' // Update fmt-chunk size mmioAscend hWave, chkData, 0 ' // Create data chunk chkData.ckid = mmioStringToFOURCC("data", 0) If mmioCreateChunk(hWave, chkData, 0) Then acmStreamClose hStream, 0 mmioClose hWave MsgBox "Error creating data chunk" Exit Function End If ReDim buffer(0) Do While szData > 0 ' // Calc output buffer size ret = acmStreamSize(hStream, 8192, szDat, ACM_STREAMSIZEF_SOURCE) If ret Then acmStreamClose hStream, 0 mmioClose hWave Exit Function End If If UBound(buffer) < szDat - 1 Then ReDim Preserve buffer(szDat - 1) End If ' // Calc header With acmHdr .cbStruct = Len(acmHdr) .lppbDst = VarPtr(buffer(0)) .lppbSrc = lpData .cbDstLength = szDat .cbSrcLength = szData End With ' // Prepare header ret = acmStreamPrepareHeader(hStream, acmHdr, 0) If ret Then acmStreamClose hStream, 0 mmioClose hWave Exit Function End If ' // Convert to PCM ret = acmStreamConvert(hStream, acmHdr, ACM_STREAMCONVERTF_BLOCKALIGN) acmStreamUnprepareHeader hStream, acmHdr, 0 If ret Then acmStreamClose hStream, 0 mmioClose hWave Exit Function End If ' // Write data If mmioWrite(hWave, buffer(0), acmHdr.cbDstLengthUsed) = -1 Then acmStreamClose hStream, 0 mmioClose hWave MsgBox "Error writing data" Exit Function End If szData = szData - acmHdr.cbSrcLengthUsed lpData = lpData + acmHdr.cbSrcLengthUsed compl = compl + acmHdr.cbSrcLengthUsed picProgress.Line (0, 0)-(compl / orSize, 1), vbRed, BF DoEvents Loop acmStreamClose hStream, 0 ' // Update data-chunk size mmioAscend hWave, chkData, 0 ' // Update RIFF-chunk size mmioAscend hWave, chkRIFF, 0 mmioClose hWave outSize = index Else: Exit Function End If picProgress.Visible = False ConvertFromMemory = True End Function Private Sub cmpPickIn_Click() Dim ofn As OPENFILENAME Dim title As String Dim filter As String Dim strInputFile As String With ofn .nMaxFile = 260 title = "Open mp3 file" filter = "Mpeg-audio files" & vbNullChar & "*.mp3" & vbNullChar strInputFile = String$(.nMaxFile, vbNullChar) .hwndOwner = Me.hWnd .lpstrTitle = StrPtr(title) .lpstrFile = StrPtr(strInputFile) .lStructSize = Len(ofn) .lpstrFilter = StrPtr(filter) If GetOpenFileName(ofn) = 0 Then Exit Sub strInputFile = Left$(strInputFile, InStr(1, strInputFile, vbNullChar) - 1) End With txtIn.Text = strInputFile End Sub Private Sub cmpPickOut_Click() Dim ofn As OPENFILENAME Dim title As String Dim filter As String Dim strOutputFile As String With ofn .nMaxFile = 260 title = "Save wave-PCM file" filter = "WAVE-PCM files" & vbNullChar & "*.wav" & vbNullChar strOutputFile = String$(.nMaxFile, vbNullChar) .hwndOwner = Me.hWnd .lpstrTitle = StrPtr(title) .lpstrFile = StrPtr(strOutputFile) .lStructSize = Len(ofn) .lpstrFilter = StrPtr(filter) .lpstrDefExt = StrPtr("wav") If GetSaveFileName(ofn) = 0 Then Exit Sub strOutputFile = Left$(strOutputFile, InStr(1, strOutputFile, vbNullChar) - 1) End With txtOut.Text = strOutputFile End Sub Private Sub Mp3Init() Dim b As curBuffer b.b(0) = 450377142658.6656@: b.b(1) = 900743977448.248@: b.b(2) = 1351114248211.6672@ b.b(3) = 1801487954948.9248@: b.b(4) = 2702228496423.3344@: b.b(5) = 3602975909897.8496@ b.b(6) = 4503737067267.712@: b.b(7) = 18941235272.0895@: b.b(8) = 4735201446.045@ b.b(9) = 10307921515.2@: b.b(10) = 13743895348.4@: b.b(11) = 3435973838.4@ memcpy Constants.bitrate(0, 1), b.b(0), 96 End Sub Private Sub Form_Load() Mp3Init End Sub
Ну да, давайте городить очередной лисапед, когда, в принципе, все средства для этого уже есть (пусть и не такие удобные, как libsndfile). При этом я сказал, что мне нужно только экспортировать в определённом формате, и это была задача № 1. А вот импортировать - желательно с поддержкой и других общепринятых кодеков, это задача № 2.
Странно, а мне показалось, что ваш тезис больше применим к вам самим. А потом, у вас времени стало резко нехватать, после того как я вам поведал о страшной тайне - интерполяции B-сплайнами.