Преобразование аудио данных Wave, нужен алгоритм

Тема в разделе "WASM.AUDIO", создана пользователем Thetrik, 25 июл 2011.

  1. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    422
    Здравствуйте дорогие форумчане!
    С целью оптимизации своей программы написанной на VB6 я делаю DLL для работы со звуковыми данными.
    Собственно у меня вот в чем загвоздка: звуковые Wave данные бывают разных форматов, т.е. с разной частотой дискретизации, с разным количеством каналов и разрядностью. Я в свою DLL вставил процедуру которая конвертирует данные в один общий формат, (который также задается вызовом функции из этой DLL),и у меня возникла проблема преобразования размера данных(например из 16->8 бит на выборку). Как можно более грамонтно сделать это преобразование?
    Я сейчас использую следующий алгоритм (код весь выкладывать на буду очень много, приведу только алгоритм):
    Код (Text):
    1. WAVEFORMAT Struct
    2.         wFormatTag dw ?
    3.         nBitPerSample dw ?
    4.         nChannels As  dw ?
    5.         nSamplesPerSec As  dd ?
    6.         nAvgBytesPerSec As  dd ?
    7.         nBlockAlign As  dw ?
    8. WAVEFORMAT ends
    9.  
    10. Convert proc USES edi esi FDATS:DWORD,FLEN:DWORD,FROMFORMAT:DWORD,TDATS:DWORD
    11.  FDATS- исходные данные
    12.  FLEN- Размер конечных данных в байтах
    13.  FROMFORMAT-Исходный формат(указатель на WaveFormat)
    14.  TDATS-Указатель на приемник преобразованных данных
    15.  1. Сначала узнаем nSamplesPerSec источника(sCnt) и приемника(dCnt) в байтах
    16.  2. Вычисляем маску для источника(sMask). Например у меня исходный nBitPerSample=16 значит маска будет 0FFFFh
    17.  3. Находим отношение nSamplesPerSec источника на nSamplesPerSecond приемника: Temp=0
    18.  4. В CX помещаем разность Источникого nBitPerSample-Приемникого nBitPerSample
    19.  5. Цикл прохода по байтам источнка:(ebx=FLEN,esi=TDATS,edi=FDATS)
    20.             mov eax,Temp    ; Поместить указатель источника
    21.             mul sCnt
    22.             add eax,FDATS
    23.             mov edi,eax
    24.             mov eax,[edi]   ; Загрузить DW источника в EAX
    25.             and eax,sMask   ; Выделить нужные биты
    26.             sal eax,cl          ; Преобразовать в BITPERSAMPLE
    27.             mov [esi],eax   ; Загрузить в TDATS
    28.             add esi,dCnt    ; Увеличиваем указатель приемника
    29.             FADD ST,ST(1)   ; Увеличиваем указатель источника
    30.             FIST Temp   ; Сохранить в память
    31.             dec ebx
    32.             jz ExitConvert
    33. 6. Выход из процедуры
    Мне кажется что это, мягко говоря, кривой код. Может кто знает алгоритм, или API какая есть чтобы переводить звуковые данные в любой формат? Буду очень благодарен :)
    P.S. За оформление прошу сильно не пинать
     
  2. rmka

    rmka Member

    Публикаций:
    0
    Регистрация:
    22 окт 2010
    Сообщения:
    107
    shr eax, 8
     
  3. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    422
    rmka
    Это понятно я в CX заношу разность и получаю сдвиг на столко на сколько нужно. Вопрос в чем, как можно выбрать вроизвольные данные, т.е. байт, слово, двойное слово от условия. В моем алгоритме берется двойное слово и к нему применяется маска, которая и дает нужный результат.Я думаю может самомодифицирующийся код использовать, чтобы уже от условия брался нужный размер данных[​IMG]
     
  4. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.862
    Зачем вам маска и разность? Множите на BitPerSampleDest/BitPerSampleSrс или делите на BitPerSampleSrc/BitPerSampleDst, в зависимости от того что больше. Ну а выборку делаете по кол-ву байт на душу населения. И ещё желательно округлять в две стороны.
     
  5. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    422
    Спасибо!!!
     
  6. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.862
    Выборку можно делать через память. Выделяете 2 четырёхбайтовых ячейки, одна для src, другая для dst. Пишите в src столько байт сколько нужно, в остаток ячейки нули. Потом читаете эту ячейку в регистр, производите операцию, пишите в dst и снова по байту записываете в выходной поток из dst. Можно конечно заморочиться и маской, но это всё оптимизации, когда уже всё будет работать.
     
  7. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    422
    Проблема возникает при записи последней ячейки, она выходит за пределы массива если nBitPerSampleDst<32
     
  8. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.862
    Или используйте метод с памятью, или комбинируйте - вначале маска, последняя часть через память.
     
  9. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    422
    Будем пробывать. Спасибо за информацию :)