MFAPI: создать WAV-файл

Тема в разделе "WASM.WIN32", создана пользователем SadKo, 7 апр 2019.

  1. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Господа! Я что-то не понимаю, как средствами MFAPI создать WAV-файл. Пробую вот так:
    Код (Text):
    1.  
    2. // test_mfapi.cpp : This file contains the 'main' function. Program execution begins and ends there.
    3. //
    4.  
    5. #include <shtypes.h>
    6. #include <shlwapi.h>
    7. #include <propvarutil.h>
    8. #include <guiddef.h>
    9. #include <propidl.h>
    10. #include <propvarutil.h>
    11. #include <mfapi.h>
    12. #include <mfidl.h>
    13. #include <mferror.h>
    14. #include <mfreadwrite.h>
    15.  
    16. int main()
    17. {
    18.    // Create SinkWriter
    19.    HRESULT hr;
    20.    IMFSinkWriter* pSinkWriter = NULL;
    21.    const WCHAR* wpath = L"test.wav";
    22.  
    23.    // Initialize the COM runtime.
    24.    hr = ::CoInitializeEx(0, COINIT_MULTITHREADED);
    25.    if (SUCCEEDED(hr))
    26.    {
    27.      // Initialize the Media Foundation platform.
    28.      ::MFStartup(MF_VERSION);
    29.    }
    30.  
    31.    // Create attributes
    32.    IMFAttributes* pAttributes = NULL;
    33.    hr = ::MFCreateAttributes(&pAttributes, 16);
    34.    if (!SUCCEEDED(hr))
    35.      return -1;
    36.  
    37.    if (SUCCEEDED(hr))
    38.      hr = pAttributes->SetGUID(MF_TRANSCODE_CONTAINERTYPE, MFTranscodeContainerType_WAVE);
    39.    if (!SUCCEEDED(hr))
    40.    {
    41.      pAttributes->Release();
    42.      return -1;
    43.    }
    44.  
    45.    // Create sink writer
    46.    hr = ::MFCreateSinkWriterFromURL(wpath, NULL, pAttributes, &pSinkWriter);
    47.    pAttributes->Release();
    48.    if (!SUCCEEDED(hr))
    49.      return -1;
    50.  
    51.  
    52.  
    53.    return 0;
    54. }
    55.  
    Функция ::MFCreateSinkWriterFromURL создаёт пустой файл и возвращает ошибку 0xc00d36fa = MF_E_CANNOT_CREATE_SINK.

    Что я делаю не так?
    --- Сообщение объединено, 7 апр 2019 ---
    Кажись, понял
    MFTranscodeContainerType_WAVE
    WAVE file container.
    Supported in Windows 8.1 and and later.

    [​IMG]
    --- Сообщение объединено, 7 апр 2019 ---
    Wikipedia:
    2007 - 1991= 16 лет.
    Microsoft, вы серьёзно?
     
    Последнее редактирование: 7 апр 2019
  2. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    860
    Создавай через mmio функции.
     
  3. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.954
    В семплах на майкрософт.ком просто создается интерфейс IMFSinkWriter
    Код (Text):
    1. HRESULT hr = MFCreateSinkWriterFromURL(L"output.wmv", NULL, NULL, &pSinkWriter);
    А уже потом ему устанавливаются атрибуты.
     
  4. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    *.wmv создаётся без проблем, а вот *.wav - вылетает ошибка.
    А мне нужно писать в WAV, PCM, float32.
    --- Сообщение объединено, 8 апр 2019 ---
    Thetrik посмотрел описание функций, ОК, попробую. Но не интегрировать в омегафреймворк поддержку RIFF с самого начала - это верх долбодятлизма.
     
  5. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.954
  6. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Да я уже весь код необходимый написал по туториалам и сэмплам. Проблема в том, что я тестирую на Windows 7 всё это дело, а там запись WAV-файлов тупо не поддерживается.
     
  7. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.954
    аа. Ну значит надо было использовать другой интерфейс или другие апи.
     
  8. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Ну вот буду прилеплять доп. костыль с поддержкой mmio по совету Thetrik .
     
  9. sty

    sty Member

    Публикаций:
    0
    Регистрация:
    2 фев 2019
    Сообщения:
    102
    Стало интересно, а что дает применение средств MFAPI? Я когда с созданием WAV-файлов эксперементировал, то пользовался mmio функциями. Правда это было на Win XP. :)
     
  10. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Ну вы можете делать кодирование/декодирование налету в указанный вами формат. То есть, если вашей приложухе нужно грузить аудиофайлы, то через mfapi вы автоматом сможете грузить не только WAV. То же касается и экспорта.
     
  11. sty

    sty Member

    Публикаций:
    0
    Регистрация:
    2 фев 2019
    Сообщения:
    102
    Понял. Спасибо.
     
  12. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Лол.

    По теме: WAV и BMP - это два настолько простых формата, что имхо нет ничего зазорного в том, чтобы прописать их хексом прямо в коде, типа unsigned char header[] = {...}; Конечно, сам этот массив копипастить не нужно - его нужно засунуть в класс или функцию, но думаю это и так понятно.
     
  13. sty

    sty Member

    Публикаций:
    0
    Регистрация:
    2 фев 2019
    Сообщения:
    102
    _DEN_, сразу чувствуется, что вы не музыкант и далеки от музыкального программирования. :)

    SadKo, ловите сразу Дена на слове - вдруг, действительно, чем-то дельным поможет.
    Мне же вон с интерполяцией помог. Может и вам поможет. :)
     
  14. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    860
    Если я правильно понял, то тут можно использовать ACM - будет работать и на XP.

    Вот, мб пригодится, код с созданием WAVE файла + чанки с информацией:
    Код (Visual Basic):
    1. Public Const ARTIST_NAME                   As String = "TrickComposer_1.4"
    2. Public Const GENRE_NAME                    As String = "8 bit"
    3.  
    4. Public Function ExportToWave( _
    5.                 ByVal curSong As Song, _
    6.                 ByRef fileName As String) As Boolean
    7.     Dim Ret         As Long
    8.     Dim hWave       As Long
    9.     Dim chkRIFF     As MMCKINFO
    10.     Dim chkData     As MMCKINFO
    11.     Dim chkList     As MMCKINFO
    12.     Dim chkSub      As MMCKINFO
    13.     Dim dstFormat   As WAVEFORMATEX
    14.     Dim buffer()    As Integer
    15.     Dim Year        As String
    16.  
    17.     SetProgressState frmMain, TBPF_NORMAL
    18.  
    19.     curSong.SetPos 0
    20.  
    21.     dstFormat.wFormatTag = 1
    22.     dstFormat.wBitsPerSample = 16
    23.     dstFormat.nSamplesPerSec = curSong.SampleRate
    24.     dstFormat.nChannels = 2
    25.     dstFormat.nBlockAlign = (dstFormat.wBitsPerSample \ 8) * dstFormat.nChannels
    26.     dstFormat.nAvgBytesPerSec = dstFormat.nBlockAlign * dstFormat.nSamplesPerSec
    27.  
    28.     If Len(Dir$(fileName)) Then Kill fileName
    29.  
    30.     ' // Create wave file
    31.     hWave = mmioOpen(fileName, ByVal 0&, MMIO_WRITE Or MMIO_CREATE)
    32.     If hWave = 0 Then
    33.         MsgBox "Error creating wave file"
    34.         GoTo ExitExport
    35.     End If
    36.  
    37.     ' // Create RIFF-WAVE chunk
    38.     chkRIFF.fccType = mmioStringToFOURCC("WAVE", 0)
    39.     If mmioCreateChunk(hWave, chkRIFF, MMIO_CREATERIFF) Then
    40.         mmioClose hWave
    41.         MsgBox "Error creating RIFF-WAVE chunk"
    42.         GoTo ExitExport
    43.     End If
    44.      
    45.     ' // Create fmt chunk
    46.     chkData.ckid = mmioStringToFOURCC("fmt", 0)
    47.     If mmioCreateChunk(hWave, chkData, 0) Then
    48.         mmioClose hWave
    49.         MsgBox "Error creating fmt chunk"
    50.         GoTo ExitExport
    51.     End If
    52.  
    53.     ' // Write format
    54.     If mmioWrite(hWave, dstFormat, Len(dstFormat)) = -1 Then
    55.         mmioClose hWave
    56.         MsgBox "Error writing format"
    57.         GoTo ExitExport
    58.     End If
    59.  
    60.     ' // Update fmt-chunk size
    61.     mmioAscend hWave, chkData, 0
    62.  
    63.     ' // Create data chunk
    64.     chkData.ckid = mmioStringToFOURCC("data", 0)
    65.     If mmioCreateChunk(hWave, chkData, 0) Then
    66.         mmioClose hWave
    67.         MsgBox "Error creating data chunk"
    68.         GoTo ExitExport
    69.     End If
    70.  
    71.     ReDim buffer(12000 - 1)
    72.  
    73.     ' // Write pause
    74.     If mmioWrite(hWave, buffer(0), (UBound(buffer) + 1) * Len(buffer(0))) = -1 Then
    75.         mmioClose hWave
    76.         MsgBox "Error writing data"
    77.         GoTo ExitExport
    78.     End If
    79.  
    80.     Do While curSong.GetPos <= curSong.SongDuration
    81.  
    82.         DoEvents
    83.  
    84.         curSong.Play buffer()
    85.  
    86.         ' // Write data
    87.         If mmioWrite(hWave, buffer(0), (UBound(buffer) + 1) * Len(buffer(0))) = -1 Then
    88.             mmioClose hWave
    89.             MsgBox "Error writing data"
    90.             GoTo ExitExport
    91.         End If
    92.  
    93.         ZeroMemory buffer(0), (UBound(buffer) + 1) * Len(buffer(0))
    94.      
    95.         SetProgressValue frmMain, curSong.GetPos() / curSong.SongDuration()
    96.      
    97.         'frmMain.picProgress.Line (0, 0)-(curSong.GetPos(), 1), vbRed, BF
    98.  
    99.     Loop
    100.      
    101.     ' // Update data-chunk size
    102.     mmioAscend hWave, chkData, 0
    103.  
    104.     ' // Create LIST chunk
    105.     chkList.fccType = mmioStringToFOURCC("INFO", 0)
    106.     If mmioCreateChunk(hWave, chkList, MMIO_CREATELIST) Then
    107.         mmioClose hWave
    108.         MsgBox "Error creating LIST-INFO chunk"
    109.         GoTo ExitExport
    110.     End If
    111.  
    112.     ' // Create IART chunk
    113.     chkSub.ckid = mmioStringToFOURCC("IART", 0)
    114.     If mmioCreateChunk(hWave, chkSub, 0) Then
    115.         mmioClose hWave
    116.         MsgBox "Error creating IART chunk"
    117.         GoTo ExitExport
    118.     End If
    119.  
    120.     ' // Write IART
    121.     If mmioWrite(hWave, ByVal StrPtr(StrConv(ARTIST_NAME, vbFromUnicode)), Len(ARTIST_NAME)) = -1 Then
    122.         mmioClose hWave
    123.         MsgBox "Error writing IART"
    124.         GoTo ExitExport
    125.     End If
    126.  
    127.     ' // Update IART-chunk size
    128.     mmioAscend hWave, chkSub, 0
    129.  
    130.     Year = CStr(DateTime.Year(Now))
    131.  
    132.     ' // Create ICRD chunk
    133.     chkSub.ckid = mmioStringToFOURCC("ICRD", 0)
    134.     If mmioCreateChunk(hWave, chkSub, 0) Then
    135.         mmioClose hWave
    136.         MsgBox "Error creating ICRD chunk"
    137.         GoTo ExitExport
    138.     End If
    139.  
    140.     ' // Write ICRD
    141.     If mmioWrite(hWave, ByVal StrPtr(StrConv(Year, vbFromUnicode)), Len(Year)) = -1 Then
    142.         mmioClose hWave
    143.         MsgBox "Error writing ICRD"
    144.         GoTo ExitExport
    145.     End If
    146.  
    147.     ' // Update ICRD-chunk size
    148.     mmioAscend hWave, chkSub, 0
    149.  
    150.     ' // Create IGNR chunk
    151.     chkSub.ckid = mmioStringToFOURCC("IGNR", 0)
    152.     If mmioCreateChunk(hWave, chkSub, 0) Then
    153.         mmioClose hWave
    154.         MsgBox "Error creating IGNR chunk"
    155.         GoTo ExitExport
    156.     End If
    157.  
    158.     ' // Write IGNR
    159.     If mmioWrite(hWave, ByVal StrPtr(StrConv(GENRE_NAME, vbFromUnicode)), Len(GENRE_NAME)) = -1 Then
    160.         mmioClose hWave
    161.         MsgBox "Error writing IGNR"
    162.         GoTo ExitExport
    163.     End If
    164.  
    165.     ' // Update IGNR-chunk size
    166.     mmioAscend hWave, chkSub, 0
    167.  
    168.     ' // Create INAM chunk
    169.     chkSub.ckid = mmioStringToFOURCC("INAM", 0)
    170.     If mmioCreateChunk(hWave, chkSub, 0) Then
    171.         mmioClose hWave
    172.         MsgBox "Error creating INAM chunk"
    173.         GoTo ExitExport
    174.     End If
    175.  
    176.     ' // Write INAM
    177.     If mmioWrite(hWave, ByVal StrPtr(StrConv(curSong.Name, vbFromUnicode)), Len(curSong.Name)) = -1 Then
    178.         mmioClose hWave
    179.         MsgBox "Error writing INAM"
    180.         GoTo ExitExport
    181.     End If
    182.  
    183.     ' // Update INAM-chunk size
    184.     mmioAscend hWave, chkSub, 0
    185.  
    186.     ' // Update LIST-chunk size
    187.     mmioAscend hWave, chkList, 0
    188.  
    189.     ' // Update RIFF-chunk size
    190.     mmioAscend hWave, chkRIFF, 0
    191.  
    192.     ExportToWave = True
    193.  
    194. ExitExport:
    195.  
    196.     mmioClose hWave
    197.  
    198.     SetProgressState frmMain, TBPF_NOPROGRESS
    199.  
    200. End Function
    В цикле просто извлекаются PCM данные и пишутся в файл.
     
  15. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    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?
     
  16. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    860
    Есть на VB6. https://wasm.in/threads/vokoder-na-vb6.31874/ - тут класс декодирует из произволного WAV в необходимый PCM.
    Вот есть декодирование из MP3 в PCM (тоже VB6):
    Код (Visual Basic):
    1. Option Explicit
    2.  
    3. Private Type OPENFILENAME
    4.     lStructSize         As Long
    5.     hwndOwner           As Long
    6.     hInstance           As Long
    7.     lpstrFilter         As Long
    8.     lpstrCustomFilter   As Long
    9.     nMaxCustFilter      As Long
    10.     nFilterIndex        As Long
    11.     lpstrFile           As Long
    12.     nMaxFile            As Long
    13.     lpstrFileTitle      As Long
    14.     nMaxFileTitle       As Long
    15.     lpstrInitialDir     As Long
    16.     lpstrTitle          As Long
    17.     Flags               As Long
    18.     nFileOffset         As Integer
    19.     nFileExtension      As Integer
    20.     lpstrDefExt         As Long
    21.     lCustData           As Long
    22.     lpfnHook            As Long
    23.     lpTemplateName      As Long
    24. End Type
    25.  
    26. Private Type curBuffer
    27.     b(15)               As Currency
    28. End Type
    29.  
    30. Private Type mp3Const
    31.     bitrate(1, 15)      As Integer
    32.     smprate(2, 3)       As Long
    33. End Type
    34.  
    35. Private Type LARGE_INTEGER
    36.     lowpart             As Long
    37.     highpart            As Long
    38. End Type
    39.  
    40. Private Type WAVEFORMATEX
    41.     wFormatTag          As Integer
    42.     nChannels           As Integer
    43.     nSamplesPerSec      As Long
    44.     nAvgBytesPerSec     As Long
    45.     nBlockAlign         As Integer
    46.     wBitsPerSample      As Integer
    47.     cbSize              As Integer
    48. End Type
    49.  
    50. Private Type MPEGLAYER3WAVEFORMAT
    51.     wFormatTag          As Integer
    52.     nChannels           As Integer
    53.     nSamplesPerSec      As Long
    54.     nAvgBytesPerSec     As Long
    55.     nBlockAlign         As Integer
    56.     wBitsPerSample      As Integer
    57.     cbSize              As Integer
    58.     wID                 As Integer
    59.     fdwFlags            As Long
    60.     nBlockSize          As Integer
    61.     nFramesPerBlock     As Integer
    62.     nCodecDelay         As Integer
    63. End Type
    64.  
    65. Private Type ACMSTREAMHEADER
    66.     cbStruct            As Long
    67.     fdwStatus           As Long
    68.     lpdwUser            As Long
    69.     lppbSrc             As Long
    70.     cbSrcLength         As Long
    71.     cbSrcLengthUsed     As Long
    72.     lpdwSrcUser         As Long
    73.     lppbDst             As Long
    74.     cbDstLength         As Long
    75.     cbDstLengthUsed     As Long
    76.     lpdwDstUser         As Long
    77.     dwDriver(9)         As Long
    78. End Type
    79.  
    80. Private Type MMCKINFO
    81.     ckid                As Long
    82.     ckSize              As Long
    83.     fccType             As Long
    84.     dwDataOffset        As Long
    85.     dwFlags             As Long
    86. End Type
    87.  
    88. Private Declare Function GetOpenFileName Lib "comdlg32.dll" _
    89.                          Alias "GetOpenFileNameW" ( _
    90.                          pOpenfilename As OPENFILENAME) As Long
    91. Private Declare Function GetSaveFileName Lib "comdlg32.dll" _
    92.                          Alias "GetSaveFileNameW" ( _
    93.                          pOpenfilename As OPENFILENAME) As Long
    94. Private Declare Function memcpy Lib "kernel32" _
    95.                          Alias "RtlMoveMemory" ( _
    96.                          ByRef Destination As Any, _
    97.                          ByRef Source As Any, _
    98.                          ByVal Length As Long) As Long
    99. Private Declare Function CreateFile Lib "kernel32" _
    100.                          Alias "CreateFileW" ( _
    101.                          ByVal lpFileName As Long, _
    102.                          ByVal dwDesiredAccess As Long, _
    103.                          ByVal dwShareMode As Long, _
    104.                          lpSecurityAttributes As Any, _
    105.                          ByVal dwCreationDisposition As Long, _
    106.                          ByVal dwFlagsAndAttributes As Long, _
    107.                          ByVal hTemplateFile As Long) As Long
    108. Private Declare Function CloseHandle Lib "kernel32" ( _
    109.                          ByVal hObject As Long) As Long
    110. Private Declare Function CreateFileMapping Lib "kernel32" _
    111.                          Alias "CreateFileMappingW" ( _
    112.                          ByVal hFile As Long, _
    113.                          lpFileMappingAttributes As Any, _
    114.                          ByVal flProtect As Long, _
    115.                          ByVal dwMaximumSizeHigh As Long, _
    116.                          ByVal dwMaximumSizeLow As Long, _
    117.                          ByVal lpName As Long) As Long
    118. Private Declare Function MapViewOfFile Lib "kernel32" ( _
    119.                          ByVal hFileMappingObject As Long, _
    120.                          ByVal dwDesiredAccess As Long, _
    121.                          ByVal dwFileOffsetHigh As Long, _
    122.                          ByVal dwFileOffsetLow As Long, _
    123.                          ByVal dwNumberOfBytesToMap As Long) As Long
    124. Private Declare Function UnmapViewOfFile Lib "kernel32" ( _
    125.                          ByVal lpBaseAddress As Long) As Long
    126. Private Declare Function GetMem4 Lib "msvbvm60" ( _
    127.                          ByRef Src As Any, _
    128.                          ByRef Dst As Any) As Long
    129. Private Declare Function GetMem8 Lib "msvbvm60" ( _
    130.                          ByRef Src As Any, _
    131.                          ByRef Dst As Any) As Long
    132. Private Declare Function IsBadReadPtr Lib "kernel32" ( _
    133.                          ByRef lp As Any, _
    134.                          ByVal ucb As Long) As Long
    135. Private Declare Function SetFilePointerEx Lib "kernel32" ( _
    136.                          ByVal hFile As Long, _
    137.                          ByVal liDistanceToMoveL As Long, _
    138.                          ByVal liDistanceToMoveH As Long, _
    139.                          ByRef lpNewFilePointer As LARGE_INTEGER, _
    140.                          ByVal dwMoveMethod As Long) As Long
    141. Private Declare Function acmStreamClose Lib "msacm32" ( _
    142.                          ByVal has As Long, _
    143.                          ByVal fdwClose As Long) As Long
    144. Private Declare Function acmStreamConvert Lib "msacm32" ( _
    145.                          ByVal has As Long, _
    146.                          ByRef pash As ACMSTREAMHEADER, _
    147.                          ByVal fdwConvert As Long) As Long
    148. Private Declare Function acmStreamMessage Lib "msacm32" ( _
    149.                          ByVal has As Long, _
    150.                          ByVal uMsg As Long, _
    151.                          ByVal lParam1 As Long, _
    152.                          ByVal lParam2 As Long) As Long
    153. Private Declare Function acmStreamOpen Lib "msacm32" ( _
    154.                          ByRef phas As Any, _
    155.                          ByVal had As Long, _
    156.                          ByRef pwfxSrc As Any, _
    157.                          ByRef pwfxDst As Any, _
    158.                          ByRef pwfltr As Any, _
    159.                          ByRef dwCallback As Any, _
    160.                          ByRef dwInstance As Any, _
    161.                          ByVal fdwOpen As Long) As Long
    162. Private Declare Function acmStreamPrepareHeader Lib "msacm32" ( _
    163.                          ByVal has As Long, _
    164.                          ByRef pash As ACMSTREAMHEADER, _
    165.                          ByVal fdwPrepare As Long) As Long
    166. Private Declare Function acmStreamReset Lib "msacm32" ( _
    167.                          ByVal has As Long, _
    168.                          ByVal fdwReset As Long) As Long
    169. Private Declare Function acmStreamSize Lib "msacm32" ( _
    170.                          ByVal has As Long, _
    171.                          ByVal cbInput As Long, _
    172.                          ByRef pdwOutputBytes As Long, _
    173.                          ByVal fdwSize As Long) As Long
    174. Private Declare Function acmStreamUnprepareHeader Lib "msacm32" ( _
    175.                          ByVal has As Long, _
    176.                          ByRef pash As ACMSTREAMHEADER, _
    177.                          ByVal fdwUnprepare As Long) As Long
    178. Private Declare Function mmioClose Lib "winmm.dll" ( _
    179.                          ByVal hmmio As Long, _
    180.                          Optional ByVal uFlags As Long) As Long
    181. Private Declare Function mmioOpen Lib "winmm.dll" _
    182.                          Alias "mmioOpenW" ( _
    183.                          ByVal szFileName As Long, _
    184.                          ByRef lpmmioinfo As Any, _
    185.                          ByVal dwOpenFlags As Long) As Long
    186. Private Declare Function mmioStringToFOURCC Lib "winmm.dll" _
    187.                          Alias "mmioStringToFOURCCA" ( _
    188.                          ByVal sz As String, _
    189.                          ByVal uFlags As Long) As Long
    190. Private Declare Function mmioAscend Lib "winmm.dll" ( _
    191.                          ByVal hmmio As Long, _
    192.                          ByRef lpck As MMCKINFO, _
    193.                          ByVal uFlags As Long) As Long
    194. Private Declare Function mmioCreateChunk Lib "winmm.dll" ( _
    195.                          ByVal hmmio As Long, _
    196.                          ByRef lpck As MMCKINFO, _
    197.                          ByVal uFlags As Long) As Long
    198. Private Declare Function mmioWrite Lib "winmm.dll" ( _
    199.                          ByVal hmmio As Long, _
    200.                          ByRef pch As Any, _
    201.                          ByVal cch As Long) As Long
    202.  
    203. Private Const MMIO_CREATERIFF                 As Long = &H20
    204. Private Const MMIO_DIRTY                      As Long = &H10000000
    205. Private Const MMIO_CREATE                     As Long = &H1000
    206. Private Const MMIO_WRITE                      As Long = &H1
    207. Private Const OPEN_EXISTING                   As Long = 3
    208. Private Const PAGE_READONLY                   As Long = 2&
    209. Private Const FILE_SHARE_READ                 As Long = &H1
    210. Private Const INVALID_HANDLE_VALUE            As Long = -1
    211. Private Const GENERIC_READ                    As Long = &H80000000
    212. Private Const FILE_MAP_READ                   As Long = &H4
    213. Private Const FILE_ATTRIBUTE_NORMAL           As Long = &H80
    214. Private Const RIFF_SIGNATURE                  As Long = &H46464952
    215. Private Const WAVE_SIGNATURE                  As Long = &H45564157
    216. Private Const FMT_SIGNATURE                   As Long = &H20746D66
    217. Private Const DATA_SIGNATURE                  As Long = &H61746164
    218. Private Const FILE_END                        As Long = 2
    219. Private Const ERROR_FILE_NOT_FOUND            As Long = 2
    220. Private Const MPEGLAYER3_FLAG_PADDING_OFF     As Long = 2
    221. Private Const WAVE_FORMAT_MPEGLAYER3          As Long = &H55
    222. Private Const WAVE_FORMAT_PCM                 As Long = 1
    223. Private Const MPEGLAYER3_WFX_EXTRA_BYTES      As Long = 12
    224. Private Const MPEGLAYER3_ID_MPEG              As Long = 1
    225. Private Const ACM_STREAMSIZEF_SOURCE          As Long = &H0
    226. Private Const ACM_STREAMCONVERTF_BLOCKALIGN   As Long = &H4
    227.  
    228. Private Constants   As mp3Const
    229.  
    230. Private Sub cmdConvert_Click()
    231.     Dim hFile   As Long
    232.     Dim hMap    As Long
    233.     Dim lpData  As Long
    234.     Dim errNum  As Long
    235.     Dim size    As LARGE_INTEGER
    236.  
    237.     hFile = CreateFile(StrPtr(txtIn.Text), GENERIC_READ, FILE_SHARE_READ, ByVal 0&, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
    238.  
    239.     If hFile = INVALID_HANDLE_VALUE Then
    240.         If Err.LastDllError = ERROR_FILE_NOT_FOUND Then
    241.             MsgBox "Input file not found"
    242.         Else
    243.             MsgBox "Error occured"
    244.         End If
    245.         Exit Sub
    246.     End If
    247.  
    248.     ' // Get file size
    249.     SetFilePointerEx hFile, 0, 0, size, FILE_END
    250.  
    251.     If size.highpart <> 0 Or size.lowpart < 0 Then
    252.         MsgBox "File too big"
    253.         Exit Sub
    254.     End If
    255.  
    256.     hMap = CreateFileMapping(hFile, ByVal 0&, PAGE_READONLY, 0, 0, 0)
    257.     CloseHandle hFile
    258.     If hMap = 0 Then
    259.         MsgBox "Error mapping creation"
    260.         Exit Sub
    261.     End If
    262.  
    263.     lpData = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)
    264.     CloseHandle hMap
    265.     If lpData = 0 Then
    266.         MsgBox "Memory mapping error"
    267.         Exit Sub
    268.     End If
    269.  
    270.     If Not ConvertFromMemory(lpData, size.lowpart) Then
    271.         MsgBox "Error during the conversion"
    272.     End If
    273.  
    274.     UnmapViewOfFile lpData
    275.  
    276. End Sub
    277.  
    278. Private Function ConvertFromMemory( _
    279.                  ByVal lpData As Long, _
    280.                  ByVal szData As Long) As Boolean
    281.     Dim hdr(9)  As Byte
    282.     Dim size    As Long
    283.     Dim ret     As Long
    284.     Dim szDat   As Long
    285.     Dim compl   As Long
    286.     Dim orSize  As Long
    287.  
    288.     If IsBadReadPtr(ByVal lpData, szData) Then Exit Function
    289.  
    290.     If szData >= 128 Then
    291.         ' // Skip ID3V1 tag
    292.         memcpy hdr(0), ByVal lpData + szData - 128, 3
    293.      
    294.         If hdr(0) = &H54 And hdr(1) = &H41 And hdr(2) = &H47 Then
    295.          
    296.             szData = szData - 128
    297.          
    298.         End If
    299.      
    300.     End If
    301.  
    302.     If szData >= 10 Then
    303.         ' // Skip ID3V2 tags from beginning
    304.         memcpy hdr(0), ByVal lpData, 10
    305.      
    306.         If hdr(0) = &H49 And hdr(1) = &H44 And hdr(2) = &H33 Then
    307.          
    308.             ' // Footer present
    309.             If hdr(5) And &H10 Then
    310.                 szData = szData - 10
    311.             End If
    312.      
    313.             size = hdr(6) * &H200000
    314.             size = size Or (hdr(7) * &H4000&)
    315.             size = size Or (hdr(8) * &H80&)
    316.             size = size Or hdr(9)
    317.             size = size + 10
    318.          
    319.             lpData = lpData + size
    320.             szData = szData - size
    321.              
    322.         Else
    323.             ' // Skip ID3V2 tags from end
    324.             memcpy hdr(0), ByVal lpData + szData - 10, 10
    325.          
    326.             If hdr(2) = &H49 And hdr(1) = &H44 And hdr(0) = &H33 Then
    327.              
    328.                 szData = szData - 10
    329.              
    330.                 size = hdr(6) * &H200000
    331.                 size = size Or (hdr(7) * &H4000&)
    332.                 size = size Or (hdr(8) * &H80&)
    333.                 size = size Or hdr(9)
    334.                 size = size + 10
    335.          
    336.                 szData = szData - size
    337.              
    338.             End If
    339.          
    340.         End If
    341.  
    342.     End If
    343.  
    344.     If szData < 4 Then Exit Function
    345.  
    346.     ' // Find a frame sync
    347.     Do
    348.  
    349.         GetMem4 ByVal lpData, hdr(0)
    350.      
    351.         If hdr(0) = &HFF And (hdr(1) And &HE0) = &HE0 Then
    352.             Dim vers    As Long
    353.             Dim layer   As Long
    354.             Dim bitrate As Long
    355.             Dim smprate As Long
    356.             Dim padding As Long
    357.             Dim channel As Long
    358.             Dim format  As MPEGLAYER3WAVEFORMAT
    359.          
    360.             vers = (hdr(1) And &H18) \ 8
    361.             If vers = 1 Then Exit Function
    362.  
    363.             layer = (hdr(1) And &H6) \ 2
    364.             If layer <> 1 Then Exit Function ' Only Layer 3
    365.  
    366.             If vers = 3 Then
    367.                 bitrate = Constants.bitrate(0, (hdr(2) And &HF0) \ &H10)
    368.             Else
    369.                 bitrate = Constants.bitrate(1, (hdr(2) And &HF0) \ &H10)
    370.             End If
    371.  
    372.             If vers = 3 Then
    373.                 smprate = Constants.smprate(0, (hdr(2) And &HC) \ &H4)
    374.             ElseIf vers = 2 Then
    375.                 smprate = Constants.smprate(1, (hdr(2) And &HC) \ &H4)
    376.             Else
    377.                 smprate = Constants.smprate(2, (hdr(2) And &HC) \ &H4)
    378.             End If
    379.          
    380.             padding = (hdr(2) And &H2) \ 2
    381.             channel = -(((hdr(3) And &HC0) \ 64) <> 3) + 1
    382.          
    383.             If vers = 3 Then
    384.                 size = Int(144000 * bitrate / smprate) + padding
    385.             Else
    386.                 size = Int(72000 * bitrate / smprate) + padding
    387.             End If
    388.  
    389.             With format
    390.                 .wFormatTag = WAVE_FORMAT_MPEGLAYER3
    391.                 .cbSize = MPEGLAYER3_WFX_EXTRA_BYTES
    392.                 .nChannels = channel
    393.                 .nAvgBytesPerSec = bitrate * 128
    394.                 .wBitsPerSample = 0
    395.                 .nBlockAlign = 1
    396.                 .nSamplesPerSec = smprate
    397.                 .nFramesPerBlock = 1
    398.                 .nCodecDelay = 0
    399.                 .fdwFlags = MPEGLAYER3_FLAG_PADDING_OFF
    400.                 .wID = MPEGLAYER3_ID_MPEG
    401.                 .nBlockSize = size
    402.             End With
    403.  
    404.             Exit Do
    405.          
    406.         End If
    407.      
    408.         lpData = lpData + 1
    409.         szData = szData - 1
    410.      
    411.     Loop While szData >= 4
    412.  
    413.     If szData > 0 And format.wFormatTag = WAVE_FORMAT_MPEGLAYER3 Then
    414.         ' // Try to convert
    415.         Dim hStream     As Long
    416.         Dim dstFormat   As WAVEFORMATEX
    417.         Dim buffer()    As Byte
    418.         Dim acmHdr      As ACMSTREAMHEADER
    419.         Dim outSize     As Long
    420.         Dim index       As Long
    421.      
    422.         orSize = szData
    423.         picProgress.Cls
    424.         picProgress.Visible = True
    425.      
    426.         With dstFormat
    427.             .cbSize = Len(dstFormat)
    428.             .nChannels = format.nChannels
    429.             .nSamplesPerSec = format.nSamplesPerSec
    430.             .wBitsPerSample = 16
    431.             .nBlockAlign = (.wBitsPerSample \ 8) * .nChannels
    432.             .nAvgBytesPerSec = .nBlockAlign * .nSamplesPerSec
    433.             .wFormatTag = WAVE_FORMAT_PCM
    434.         End With
    435.      
    436.         ' // Open conversion stream
    437.         ret = acmStreamOpen(hStream, 0, format, dstFormat, ByVal 0&, ByVal 0&, ByVal 0&, 0)
    438.         If ret Then Exit Function
    439.      
    440.         Dim hWave       As Long
    441.         Dim chkRIFF     As MMCKINFO
    442.         Dim chkData     As MMCKINFO
    443.      
    444.         ' // Create wave file
    445.         hWave = mmioOpen(StrPtr(txtOut.Text), ByVal 0, MMIO_WRITE Or MMIO_CREATE)
    446.         If hWave = 0 Then
    447.             acmStreamClose hStream, 0
    448.             MsgBox "Error creating wave file"
    449.             Exit Function
    450.         End If
    451.      
    452.         ' // Create RIFF-WAVE chunk
    453.         chkRIFF.fccType = mmioStringToFOURCC("WAVE", 0)
    454.         If mmioCreateChunk(hWave, chkRIFF, MMIO_CREATERIFF) Then
    455.             acmStreamClose hStream, 0
    456.             mmioClose hWave
    457.             MsgBox "Error creating RIFF-WAVE chunk"
    458.             Exit Function
    459.         End If
    460.      
    461.         ' // Create fmt chunk
    462.         chkData.ckid = mmioStringToFOURCC("fmt", 0)
    463.         If mmioCreateChunk(hWave, chkData, 0) Then
    464.             acmStreamClose hStream, 0
    465.             mmioClose hWave
    466.             MsgBox "Error creating fmt chunk"
    467.             Exit Function
    468.         End If
    469.      
    470.         ' // Write format
    471.         If mmioWrite(hWave, dstFormat, Len(dstFormat)) = -1 Then
    472.             acmStreamClose hStream, 0
    473.             mmioClose hWave
    474.             MsgBox "Error writing format"
    475.             Exit Function
    476.         End If
    477.      
    478.         ' // Update fmt-chunk size
    479.         mmioAscend hWave, chkData, 0
    480.      
    481.         ' // Create data chunk
    482.         chkData.ckid = mmioStringToFOURCC("data", 0)
    483.         If mmioCreateChunk(hWave, chkData, 0) Then
    484.             acmStreamClose hStream, 0
    485.             mmioClose hWave
    486.             MsgBox "Error creating data chunk"
    487.             Exit Function
    488.         End If
    489.      
    490.         ReDim buffer(0)
    491.      
    492.         Do While szData > 0
    493.      
    494.             ' // Calc output buffer size
    495.             ret = acmStreamSize(hStream, 8192, szDat, ACM_STREAMSIZEF_SOURCE)
    496.             If ret Then
    497.                 acmStreamClose hStream, 0
    498.                 mmioClose hWave
    499.                 Exit Function
    500.             End If
    501.          
    502.             If UBound(buffer) < szDat - 1 Then
    503.                 ReDim Preserve buffer(szDat - 1)
    504.             End If
    505.          
    506.             ' // Calc header
    507.             With acmHdr
    508.                 .cbStruct = Len(acmHdr)
    509.                 .lppbDst = VarPtr(buffer(0))
    510.                 .lppbSrc = lpData
    511.                 .cbDstLength = szDat
    512.                 .cbSrcLength = szData
    513.             End With
    514.          
    515.             ' // Prepare header
    516.             ret = acmStreamPrepareHeader(hStream, acmHdr, 0)
    517.             If ret Then
    518.                 acmStreamClose hStream, 0
    519.                 mmioClose hWave
    520.                 Exit Function
    521.             End If
    522.          
    523.             ' // Convert to PCM
    524.             ret = acmStreamConvert(hStream, acmHdr, ACM_STREAMCONVERTF_BLOCKALIGN)
    525.             acmStreamUnprepareHeader hStream, acmHdr, 0
    526.          
    527.             If ret Then
    528.                 acmStreamClose hStream, 0
    529.                 mmioClose hWave
    530.                 Exit Function
    531.             End If
    532.          
    533.             ' // Write data
    534.             If mmioWrite(hWave, buffer(0), acmHdr.cbDstLengthUsed) = -1 Then
    535.                 acmStreamClose hStream, 0
    536.                 mmioClose hWave
    537.                 MsgBox "Error writing data"
    538.                 Exit Function
    539.             End If
    540.      
    541.             szData = szData - acmHdr.cbSrcLengthUsed
    542.             lpData = lpData + acmHdr.cbSrcLengthUsed
    543.             compl = compl + acmHdr.cbSrcLengthUsed
    544.          
    545.             picProgress.Line (0, 0)-(compl / orSize, 1), vbRed, BF
    546.             DoEvents
    547.          
    548.         Loop
    549.      
    550.         acmStreamClose hStream, 0
    551.      
    552.         ' // Update data-chunk size
    553.         mmioAscend hWave, chkData, 0
    554.         ' // Update RIFF-chunk size
    555.         mmioAscend hWave, chkRIFF, 0
    556.      
    557.         mmioClose hWave
    558.      
    559.         outSize = index
    560.      
    561.     Else:   Exit Function
    562.     End If
    563.  
    564.     picProgress.Visible = False
    565.  
    566.     ConvertFromMemory = True
    567.  
    568. End Function
    569.  
    570. Private Sub cmpPickIn_Click()
    571.     Dim ofn             As OPENFILENAME
    572.     Dim title           As String
    573.     Dim filter          As String
    574.     Dim strInputFile    As String
    575.  
    576.     With ofn
    577.  
    578.         .nMaxFile = 260
    579.         title = "Open mp3 file"
    580.         filter = "Mpeg-audio files" & vbNullChar & "*.mp3" & vbNullChar
    581.         strInputFile = String$(.nMaxFile, vbNullChar)
    582.      
    583.         .hwndOwner = Me.hWnd
    584.         .lpstrTitle = StrPtr(title)
    585.         .lpstrFile = StrPtr(strInputFile)
    586.         .lStructSize = Len(ofn)
    587.         .lpstrFilter = StrPtr(filter)
    588.      
    589.         If GetOpenFileName(ofn) = 0 Then Exit Sub
    590.      
    591.         strInputFile = Left$(strInputFile, InStr(1, strInputFile, vbNullChar) - 1)
    592.      
    593.     End With
    594.  
    595.     txtIn.Text = strInputFile
    596.  
    597. End Sub
    598.  
    599. Private Sub cmpPickOut_Click()
    600.     Dim ofn             As OPENFILENAME
    601.     Dim title           As String
    602.     Dim filter          As String
    603.     Dim strOutputFile   As String
    604.  
    605.     With ofn
    606.  
    607.         .nMaxFile = 260
    608.         title = "Save wave-PCM file"
    609.         filter = "WAVE-PCM files" & vbNullChar & "*.wav" & vbNullChar
    610.         strOutputFile = String$(.nMaxFile, vbNullChar)
    611.      
    612.         .hwndOwner = Me.hWnd
    613.         .lpstrTitle = StrPtr(title)
    614.         .lpstrFile = StrPtr(strOutputFile)
    615.         .lStructSize = Len(ofn)
    616.         .lpstrFilter = StrPtr(filter)
    617.         .lpstrDefExt = StrPtr("wav")
    618.      
    619.         If GetSaveFileName(ofn) = 0 Then Exit Sub
    620.      
    621.         strOutputFile = Left$(strOutputFile, InStr(1, strOutputFile, vbNullChar) - 1)
    622.      
    623.     End With
    624.  
    625.     txtOut.Text = strOutputFile
    626.  
    627. End Sub
    628.  
    629. Private Sub Mp3Init()
    630.     Dim b   As curBuffer
    631.  
    632.     b.b(0) = 450377142658.6656@:    b.b(1) = 900743977448.248@:     b.b(2) = 1351114248211.6672@
    633.     b.b(3) = 1801487954948.9248@:   b.b(4) = 2702228496423.3344@:   b.b(5) = 3602975909897.8496@
    634.     b.b(6) = 4503737067267.712@:    b.b(7) = 18941235272.0895@:     b.b(8) = 4735201446.045@
    635.     b.b(9) = 10307921515.2@:        b.b(10) = 13743895348.4@:       b.b(11) = 3435973838.4@
    636.      
    637.     memcpy Constants.bitrate(0, 1), b.b(0), 96
    638.  
    639. End Sub
    640.  
    641. Private Sub Form_Load()
    642.     Mp3Init
    643. End Sub
    644.  
     

    Вложения:

    • Mp3_to_wave.zip
      Размер файла:
      5,7 КБ
      Просмотров:
      462
  17. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Сразу чувствуется, что у вас много свободного времени ;)
     
  18. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Ну да, давайте городить очередной лисапед, когда, в принципе, все средства для этого уже есть (пусть и не такие удобные, как libsndfile). При этом я сказал, что мне нужно только экспортировать в определённом формате, и это была задача № 1.
    А вот импортировать - желательно с поддержкой и других общепринятых кодеков, это задача № 2.
     
  19. sty

    sty Member

    Публикаций:
    0
    Регистрация:
    2 фев 2019
    Сообщения:
    102
    Странно, а мне показалось, что ваш тезис больше применим к вам самим. А потом, у вас времени стало резко нехватать, после того как я вам поведал о страшной тайне - интерполяции B-сплайнами. :)