Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.140.255.150] |
|
Страницы: (3) [1] 2 3 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Начал с самого начала, попробовал вывести параметры устройств ввода своей звуковой карты. Код:
void getnumdevaudio(UINT &nin, UINT &nout) { nin = waveInGetNumDevs(); nout = waveOutGetNumDevs(); } void getinaudioinfo(UINT nin) { WAVEINCAPS wvinfo; for(UINT i = 0; i < nin; i++) { MMRESULT wvres = waveInGetDevCaps(i, &wvinfo, sizeof(wvinfo)); if(wvres != MMSYSERR_NOERROR) { std::cout << "Ошибка определения параметров устройства № " << i << std::endl; } // if(wvres _tprintf(TEXT("%s\t%i\t%i\n"), wvinfo.szPname, wvinfo.dwFormats, wvinfo.wChannels); } // for(UINT std::cin.get(); } // fun #include <windows.h> #include <iostream> #include <stdio.h> #include <string.h> #include <tchar.h> #include "mysound.h" void main(int argc, char* argv[]) { setlocale(LC_ALL, ""); UINT nin, nout; getnumdevaudio(nin, nout); getinaudioinfo(nin); } В результате получил: IA HD Audio CD In 786431 65535 VIA HD Audio Front Microphone 786431 65535 VIA HD Audio Line In 786431 65535 VIA HD Audio Microphone 786431 65535 VIA HD Audio Stereo Mixer 786431 65535 1. Почему wvinfo.wChannels дает большое целое значение, а не значение 1 или 2, как указано в MSDN? 2. Как из цифры, которые дает wvinfo.dwFormats, получить все возможные параметры устрройства ввода, например WAVE_FORMAT_1M08 и др., которые устройство ввода поддерживает? |
Сообщ.
#2
,
|
|
|
1. Потому что такое значение возвращает драйвер устройства. Почему производители посчитали, что он должен возвращать именно такое значение...да кто бы знал бы.
2. Проверять, установлен ли соотвествующий флаг в dwFormats. Цитата #DEFINE WAVE_FORMAT_1M08 0x00000001 #DEFINE WAVE_FORMAT_1S08 0x00000002 #DEFINE WAVE_FORMAT_1M16 0x00000004 #DEFINE WAVE_FORMAT_1S16 0x00000008 ... Имхо, не стоит dwFormats воспринимать слишком серьезно. "Стандартные комбинации" параметров давно стали общепринятыми, и современными картами(драйверами) поддерживаются. Кроме того, константы для форматов 96/192 кГц 24/32 бита и многоканальных, вряд ли существуют, судя по "конструкции" 32-х битного слова dwFormats. На мой взгляд, надежней проверять поддержку формата, открывая устройство с параметрами, валидность которых под вопросом. Цитата IA HD Audio CD In 786431 65535 VIA HD Audio Front Microphone 786431 65535 VIA HD Audio Line In 786431 65535 VIA HD Audio Microphone 786431 65535 VIA HD Audio Stereo Mixer 786431 65535 семерка? |
Сообщ.
#3
,
|
|
|
Нет, у меня Windows XP. Компьютер с какой-то навороченной мультимедийной звуковой картой. У меня возникли следующие вопросы:
1. Начинаю пробовать записать звук: int tryrec(UINT nin, DWORD nbuf) // nin = 0 (домашний компьтер с одним устройством ввода - микрофоном), nbuf = 1024 - размер буфера для записи звука { TCHAR serror[128]; serror[0] = 0; MMRESULT wvres; HWAVEIN hwvindev; WAVEFORMATEX wvformat; wvformat.wFormatTag = WAVE_FORMAT_PCM; wvformat.nChannels = 1; wvformat.nSamplesPerSec = 44100; wvformat.wBitsPerSample = 16; wvformat.nBlockAlign = wvformat.nChannels*wvformat.wBitsPerSample/8; wvformat.nAvgBytesPerSec = wvformat.nSamplesPerSec*wvformat.nBlockAlign; wvformat.cbSize = sizeof(wvformat); wvres = waveInOpen( &hwvindev, nin, &wvformat, 0, 0, WAVE_FORMAT_DIRECT); if(wvres != MMSYSERR_NOERROR) { printf("Устройство %i открыть не удалось!\n", nin); return 1; } // if(wvres char *swvbuf = (char*)malloc((size_t) nbuf); swvbuf[0] = 0; WAVEHDR wvbuf; wvbuf.lpData = swvbuf; wvbuf.dwBufferLength = nbuf; wvres = waveInPrepareHeader(hwvindev, &wvbuf, sizeof(wvbuf)); if(wvres != MMSYSERR_NOERROR) { printf("Не удалось подготовить буфер для записи!\n"); wvres = waveInGetErrorText(wvres, serror, 128); _tprintf(TEXT("Ошибка: %s\n"), serror); return 2; } // if(wvres return 0; } 2. Не очень понимаю механизм записи звука. Подготавливаю буфер, делаю waveInAddBuffer, тем самым уведомляю драйвер, что туда можно записывать данные. После заполнения буфера как мне в программе узнать, что он заполнился и надо его очистить и снова подготовить для новой записи? 3. Сколько может быть буферов и можно ли их записывать последовательно, а очищать и подготавливать за один прием после заполнения последнего? Или так не делается и нужно в процессе записи в следующий буфер готовить предыдущий? 4. Есть ли функция API для записи данных из буфера в файл? Или для записи нужно использовать обычные функции записи буфера swvbuf в файл? 5. Исходя из каких соображений нужно выбирать размер буфера? |
Сообщ.
#4
,
|
|
|
1. Скорее всего, ошибка в sizeof(wvbuf). Нужен размер заголовка sizeof(WAVEHDR), а не размер переменной.
2. Вы не указали механизм уведомления в waveinopen, что равносильно callback_null. В таком варианте вы никак не узнаете. Читайте про механизмы уведомлений звуковой подсистемы. 3. Сколько может быть буферов, я не знаю, много может быть. Когда буфер заполнен, вы получаете уведомление(в это время записывается следующий в очереди буфер). В зависимости от механизма уведомления, в оконной процедуре или в специальной функции, или в потоке, вы обрабатываете буфер, вернувшийся из очереди, и снова ставите в очередь при помощи waveinaddbuffer( или уничтожаете, если он вам уже не нужен). 4. Буфер - кусок памяти, начинающийся с адреса wvbuf.lpData. Для записи в файл можно использовать все доступные функции для работы с файлами. Для записи RIFF wave файла существуют специализированные функции mmio... 5. Исходя из потребностей. Маленький буфер обеспечит меньшую задержку и более быструю реакцию вашей программы, если ваша программа должна каким-то образом реагировать на параметры звука. Но, ваша программа не сможет реагировать на события происходящие в системе чаще, чем получает управление ваш процесс. Поэтому размер буфера снизу ограничен как минимум квантом времени виндовс. Если буфер оооочень большой, а ваш компьютер ооочень медленный, в этом случае комп может не успеть сделать с буфером все что необходимо до того, как из очереди вернется следующий буфер. Хоть и гипотетически, но такая ситуация возможна, в принципе. Сверху размер буфера ограничен объемом оперативной памяти и быстродействием компа. Если без "воды", размер 0.1 с - 1.0 с вполне нормально, имхо. |
Сообщ.
#5
,
|
|
|
Добавил в код
wvbuf.dwFlags = WHDR_PREPARED; |
Сообщ.
#6
,
|
|
|
Цитата wvbuf.dwFlags = WHDR_PREPARED; Неверно. Это флаг пользователь не устанавливает. Флаги можно просто обнулять. Сравните значения sizeof(wvbuf) и sizeof(WAVEHDR). |
Сообщ.
#7
,
|
|
|
Проверил размеры:
printf("%i\t%i\n", sizeof(WAVEHDR), sizeof(wvbuf)); wvbuf.dwFlags = WHDR_PREPARED; The lpData, dwBufferLength, and dwFlags members must be set before calling the waveInPrepareHeader or waveOutPrepareHeader function. Добавлено Мне не очень понятно по поводу буфера. Я задаю один буфер, его размеры и другие параметры. Достаточно указать только один буфер, а драйвер сам создаст нужное количество буферов? Или мне нужно завать количество буферов самому? Например, так: WAVEHDR wvbuf1, wvbuf2, wvbuf3 |
Сообщ.
#8
,
|
|
|
Цитата The lpData, dwBufferLength, and dwFlags members must be set before calling the waveInPrepareHeader or waveOutPrepareHeader function. The lpData, dwBufferLength, and dwFlags members of the WAVEHDR structure must be set before calling this function (dwFlags must be zero). Цитата Получилось, что они одинаковые (32) Значит, мое предположение было ошибочным. А если обнулить флаги? Цитата Мне не очень понятно по поводу буфера. Я задаю один буфер, его размеры и другие параметры. Достаточно указать только один буфер, а драйвер сам создаст нужное количество буферов? Или мне нужно завать количество буферов самому? Вы описываете все буферы. Не количество, а ВСЕ буферы. Как минимум необходимы два буфера. |
Сообщ.
#9
,
|
|
|
Спасибо за помощь. С обнуленным флагом все работает. Опять возникли вопросы (вызваны они наверное тем, что раньше с CALLBACK функциями в явном виде не приходилось работать):
1. У меня консольное приложение. В каком месте функции tryrec нужно описывать функцию уведомления? Непосредственно вместо нуля в определении функции waveInOpen или в виде отдельной фунции в заголовочном файле? В последнем случае в waveInOpen нужно указывать указатель на функцию уведомления? 2. Как организовать в консольном приложении оповещение о заполненности буферов? |
Сообщ.
#10
,
|
|
|
Цитата tumanovalex @ Как организовать в консольном приложении оповещение о заполненности буферов? Добавить в приложение функцию: //Процедура CallBack procedure CallBackZvyk(HWAVEx:THandle;UINT:Cardinal;Instance:DWORD; Param1:DWORD;Param2:DWORD);stdcall; var Hdr:PWaveHdr;I: Integer; begin if UINT = WOM_DONE then Err := WaveOutOpen(WaveOut, 0, @WaveFormat, Cardinal(@CallBackZvyk), 0, CALLBACK_FUNCTION); |
Сообщ.
#11
,
|
|
|
Видимо, я опять что-то не понял. Попытка использования функции окончилась неудачей. Сделал пустую функцию:
void CALLBACK waveInProc(HWAVEIN hwi, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) { switch(uMsg) { case WIM_OPEN: break; case WIM_DATA: break; case WIM_CLOSE: break; } } wvres = waveInOpen( &hwvindev, nin, &wvformat, (DWORD_PTR) (*waveInProc), 0, WAVE_FORMAT_DIRECT | СALLBACK_FUNCTION); |
Сообщ.
#12
,
|
|
|
Я не сишник. Возможно, проблема в dword_ptr вместо dword. Или в (DWORD_PTR) (*waveInProc). Без понятия.
Кстати, флаг WAVE_FORMAT_DIRECT не нужен, поскольку вы запрашиваете данные непосредственно от устройства (nin=0) и в формате WAVE_FORMAT_PCM. АСМ при любом раскладе задействован не будет. Если запрошенный формат не подерживается, устройство просто не удастся открыть. WaveInOpen завершится с ошибкой WAVERR_BADFORMAT. |
Сообщ.
#13
,
|
|
|
Цитата tumanovalex @ Подскажите, пожалуйста, как правильно вызывать CALLBACK функцию в моем случае. Цитата tumanovalex @ Видимо, я опять что-то не понял. Видимо.... Ты не будешь вызывать эту функцию. Ее будет вызывать СИСТЕМА. А для этого необходимо (в первую очередь) соблюсти СОГЛАШЕНИЕ О ВЫЗОВАХ данной функции. Это выполнено? Добавлено Цитата tumanovalex @ Вызов функции Это не ВЫЗОВ функции. Это всего лишь попытка ОТКРЫТЬ устройство с определенными параметрами. И судя по: Цитата tumanovalex @ окончился необработанным исключением параметры не соответствуют заявленным системой. |
Сообщ.
#14
,
|
|
|
Я неправильно сформулировал, имел в виду, как правильно записать свою функцию и сделать на нее ссылку в waveInOpen.
|
Сообщ.
#15
,
|
|
|
Как оказалось, ошибка возникает в строке
wvres = waveInStart(hwvindev); До начала записи я делаю следующее: char *swvbuf[16]; for(UINT i = 0; i < nbuf; i++) { swvbuf[i] = (char*)malloc((size_t) nbufsize); swvbuf[i][0] = 0; wvbuf.lpData = swvbuf[i]; wvbuf.dwFlags = 0; wvbuf.dwLoops = 0; wvbuf.dwUser = 0; wvbuf.dwBufferLength = nbufsize; wvres = waveInPrepareHeader(hwvindev, &wvbuf, sizeof(wvbuf)); errormes("Не удалось подготовить буфер для записи!\n", wvres); wvres = waveInAddBuffer(hwvindev, &wvbuf, sizeof(wvbuf)); errormes("Не удалось добавить буфер для записи!\n", wvres); } // for(UINT i = 0; i < nbuf; i++) Прикреплённый файлMySound.zip (9,77 Кбайт, скачиваний: 373) |