Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.133.86.172] |
|
Страницы: (2) [1] 2 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Здравствуйте, уважаемые программисты. Это моё первое сообщение а этом форуме.
Пытаюсь с помощью MSDN запустить простейший вывод звука (из массива), приложение компилируется и даже запускается. Но звука нет. Предполагаю, что либо звук не тот я мысленно нарисовал в char-массиве, либо нужно программно задержаться после вызова waveOutWrite(), чтобы дать ему время прозвучать... // ПРОГРАММА ТЕСТИРОВАНИЯ Waveform-Audio ФУНКЦИЙ #include <windows.h> #include <mmsystem.h> //#include <windowsx.h> int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int) { char szText[80]; WAVEHDR whdr; // буфер для звука char szBuffer[88200]; // столько байт на 1 секундный сэмпл потребовалось for (UINT i=0; i<88200; i++) // формируем звуковой массив { szBuffer = rand(); // генерируем случайные числа для шума } whdr.lpData = szBuffer; // указатель звукового буфера (тип char *). whdr.dwBufferLength = 88200; // размер буфера в байтах. whdr.dwFlags = WHDR_PREPARED; // Буфер подготовлен (зафиксирован в памяти) whdr.dwLoops = 0; // В обычном режиме, без циклов, поле должно быть нулевым. WAVEFORMATEX wfx; // для получения описателя звукового устройства: wfx.wFormatTag = WAVE_FORMAT_PCM; // wav-формат wfx.nChannels = 1; // моно - звук wfx.nSamplesPerSec = 44100; // 44100 Гц wfx.nAvgBytesPerSec = 88200; // байт в секунду wfx.nBlockAlign = 2; // 2 байта на сэмпл-столбик wfx.wBitsPerSample = 16; // 16-битный сэмпл-столбик wfx.cbSize = 0; // For only WAVE_FORMAT_PCM formats, this member is ignored HWAVEOUT hWO; // handle identifying the open waveform-audio output device if(waveOutOpen(&hWO, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL) == MMSYSERR_NOERROR) { wsprintf(szText, "waveOutOpen() СРАБОТАЛА УСПЕШНО! hWO = 0%X", hWO); MessageBox(NULL, szText, "GOOD INFO", MB_OK); } else MessageBox(NULL, "waveOutOpen() НЕ СРАБОТАЛА!", "ERROR", MB_OK); waveOutPrepareHeader(hWO, &whdr, sizeof(whdr)); waveOutWrite(hWO, &whdr, sizeof(whdr)); UINT X; X = auxGetNumDevs(); // A return value of zero means that no devices are present or that an error occurred. wsprintf(szText, "Значение равно %d", X); MessageBox(NULL, szText, "Значение переменной X", MB_OK); waveOutReset(/*HWAVEOUT hwo*/ hWO); waveOutClose(/*HWAVEOUT hwo*/ hWO); return 0; } |
Сообщ.
#2
,
|
|
|
По-моему, данный код генерирует 22 кГц звук низкой амплитуды. Проверку работоспособности кода надо делать с помощью спец. аппаратуры. Человек не слышит звук такой частоты.
|
Сообщ.
#3
,
|
|
|
Я переделал исходник (см. выше), теперь в цикле формирования массива используется функция rand(), чтобы получить хотя бы какое-то подобие шума. Всё равно тишина.
Думаю, проблема может быть зарыта в том, что буфер должен быть очень коротким (десятки и сотни миллисекунд), и по всей видимости надо как-то отслеживать поведение драйвера звуковой платы (а именно прекращение воспроизведения коротенького упомянутого буфера, чтобы специальная callback-функция подкинула драйверу очередную порцию звука, т.е. очередной заранее подготовленный буфер). Только интересно бы увидеть, как это сделать в коде. Я пока не нашёл ни одного простого примера, либо примеры настолько сложны, что можно запутаться во множестве непонятных и незнакомых функций. |
Сообщ.
#4
,
|
|
|
Я писал плееры/рекордеры только на ВБ6. При изучении использовал этот пример от MS.
|
Сообщ.
#5
,
|
|
|
Если Вам нужно просто выводить звук, может быть проще использовать универсальную АПИ mciSendString из библиотеки Winmm.dll
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_mcisendstring.asp mciSendString ("open " + """ + sFiles + """ , "", %NULL, hDlg) mciSendString ("play " + """ + sFiles + """ + " notify", "", 0, hDlg) и когда в процедуре обработки окна получаем сообщение MM_MCINOTIFY проверяем что музфка отыграла по WPARAM=MCI_NOTIFY_SUCCESSFUL шлем команду закрытия mciSendString ("close " + """ + sFiles + """, "", %NULL, %NULL) хотя если простой вывод без окон то можно убрать " notify" тогда просто будет гудеть от начала и до конца. |
Сообщ.
#6
,
|
|
|
Цель - научиться пользоваться функциями именно низкоуровневого доступа к звуковой карте (waveOutWrite и т.п.).
Эти функции мне интересны возможностью почти полного контроля над выходами/входами звуковой карты. |
Сообщ.
#7
,
|
|
|
Какой кайф! Заработал генератор белого шума (пока длительностью в 1 секунду, но это уже по барабану, я получил таки контроль над выходом звуковой карты!)
Исправленный исходник для Visual C++ // ПРОГРАММА ТЕСТИРОВАНИЯ Waveform-Audio ФУНКЦИЙ #include <windows.h> #include <mmsystem.h> //#include <windowsx.h> int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int) { char szText[80]; const int SIZE = 88200; // количество байтов для сэмпла WAVEHDR whdr; // структура для буфера звука char szBuffer[SIZE]; // сколько байт на сэмпл потребовалось (88200 для 1 секунды звучания) for (UINT i=0; i<SIZE; i++) // формируем звуковой массив случайных чисел (ШУМ) { szBuffer[i] = rand(); } ZeroMemory(&whdr, sizeof(whdr)); whdr.lpData = szBuffer; // указатель звукового буфера (тип char *). whdr.dwBufferLength = SIZE; // размер буфера в байтах. WAVEFORMATEX wfx; // для получения описателя звукового устройства: ZeroMemory(&wfx, sizeof(wfx)); wfx.wFormatTag = WAVE_FORMAT_PCM; // wav-формат wfx.nChannels = 1; // моно - звук wfx.nSamplesPerSec = 44100; // 44100 Гц wfx.nAvgBytesPerSec = 4*44100; wfx.nBlockAlign = 4; wfx.wBitsPerSample = 16; // 16-битный звук wfx.cbSize = sizeof(wfx); HWAVEOUT hWO; // handle identifying the open waveform-audio output device if(waveOutOpen(&hWO, WAVE_MAPPER, &wfx, 0, 0, CALLBACK_NULL) == MMSYSERR_NOERROR) { wsprintf(szText, "waveOutOpen() СРАБОТАЛА УСПЕШНО! hWO = 0%X", hWO); MessageBox(NULL, szText, "GOOD INFO", MB_OK); } else MessageBox(NULL, "waveOutOpen() НЕ СРАБОТАЛА!", "ERROR", MB_OK); waveOutPrepareHeader(hWO, &whdr, sizeof(whdr)); waveOutWrite(hWO, &whdr, sizeof(whdr)); // вообще-то MessageBox в данном случае, чтобы успеть насладиться звуком. UINT X; X = auxGetNumDevs(); // A return value of zero means that no devices are present or that an error occurred. wsprintf(szText, "Количество аудиоустройств = %d", X); MessageBox(NULL, szText, "Значение переменной X", MB_OK); waveOutUnprepareHeader(hWO, &whdr, sizeof(whdr)); waveOutReset(hWO); waveOutClose(hWO); return 0; } Всё это было сделано с помощью найденного в интернет исходника для Delphi (см. http://dj-zef.narod.ru/soundgenerator1.html ) |
Сообщ.
#8
,
|
|
|
А вот примерно куда надо копать, чтоб не нужно было
Цитата MuratMusic @ // вообще-то MessageBox в данном случае, чтобы успеть насладиться звуком. И как по уму доступаться к 16-битным самплам... // ПРОГРАММА ТЕСТИРОВАНИЯ Waveform-Audio ФУНКЦИЙ #include <windows.h> #include <mmsystem.h> #include <stdio.h> #pragma comment(lib, "winmm.lib") #pragma comment(lib, "user32.lib") const int nRate = 44100; const int nBits = 16; const int nBytesPerSample = nBits / 8; const int nSeconds = 1; const int nSamples = nRate * nSeconds; const int nBytes = nSamples * nBytesPerSample; typedef signed short SWORD; LPCSTR GetMMSysError(MMRESULT mmResult){ const int nBufferSize = 512; static CHAR acError[nBufferSize]; waveOutGetErrorText(mmResult, acError, nBufferSize); CharToOem(acError, acError); return acError; } // Так делать некрасиво и неправильно. Только для простоты! // В реальных приложениях - либо обработка сообщений, либо мутексы, // либо эта же процедура выводит очередной "кусок" через waveOutWrite LONG bDone = FALSE; void CALLBACK waveOutProc( HWAVEOUT hwo, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) { if(uMsg == WOM_DONE || uMsg == WOM_CLOSE) InterlockedIncrement(&bDone); } int main(void){ static SWORD aswBuffer[nSamples]; // генерация звука: прямоугольные импульсы частотой nRate / 200; // при nRate = 44100 получаем 220,5 Гц // (частотный анализ записи показал 220,46 Гц) for (UINT i = 0; i < nSamples; i++) { if((i/100)%2) aswBuffer[i] = 32767; else aswBuffer[i] = -32767; } WAVEFORMATEX wfx; // для получения описателя звукового устройства: wfx.wFormatTag = WAVE_FORMAT_PCM; // wav-формат wfx.nChannels = 1; // моно - звук wfx.nSamplesPerSec = nRate; // 44100 Гц wfx.nAvgBytesPerSec = nBytesPerSample * nRate; // байт в секунду wfx.nBlockAlign = nBytesPerSample; // 2 байта на сэмпл-столбик wfx.wBitsPerSample = nBits; // 16-битный сэмпл-столбик wfx.cbSize = 0; // For only WAVE_FORMAT_PCM formats, this member is ignored HWAVEOUT hWO; // handle identifying the open waveform-audio output device MMRESULT mmResult = waveOutOpen(&hWO, WAVE_MAPPER, &wfx, (DWORD)waveOutProc, 0, CALLBACK_FUNCTION); if(mmResult == MMSYSERR_NOERROR) { printf("waveOutOpen() СРАБОТАЛА УСПЕШНО! hWO = 0%08X\n", hWO); } else printf("waveOutOpen() НЕ СРАБОТАЛА! %s\n", GetMMSysError(mmResult)); WAVEHDR whdr; whdr.lpData = (LPSTR)aswBuffer; whdr.dwBufferLength = nBytes; // размер буфера в байтах. whdr.dwFlags = 0; // Буфер подготовлен (зафиксирован в памяти) whdr.dwLoops = 0; // В обычном режиме, без циклов, поле должно быть нулевым. mmResult = waveOutPrepareHeader(hWO, &whdr, sizeof(whdr)); if(mmResult == MMSYSERR_NOERROR) { printf("waveOutPrepareHeader() СРАБОТАЛА УСПЕШНО!\n"); } else printf("waveOutPrepareHeader() НЕ СРАБОТАЛА! %s\n", GetMMSysError(mmResult)); waveOutSetVolume(hWO, 0xFFFF); mmResult = waveOutWrite(hWO, &whdr, sizeof(whdr)); if(mmResult == MMSYSERR_NOERROR) { printf("waveOutWrite() СРАБОТАЛА УСПЕШНО!\n"); } else printf("waveOutWrite() НЕ СРАБОТАЛА! %s\n", GetMMSysError(mmResult)); printf("Значение waveOutGetNumDevs() равно %d", waveOutGetNumDevs()); // В реальной программе, само собой, так не делают... for(;;){ if(bDone) break; } waveOutClose(hWO); return 0; } Блин, сделал еще с утра, так с предновогодней суетой не было времени кинуть... |
Сообщ.
#9
,
|
|
|
Спасибо, скоро постараюсь досконально разобрать по полочкам.
|
Сообщ.
#10
,
|
|
|
Цитата MuratMusic @ Цель - научиться пользоваться функциями именно низкоуровневого доступа к звуковой карте (waveOutWrite и т.п.). Я возможно разочарую, но waveOutWrite ничего общего с низкоуровневыми функциями не имеет. На случай, если понадобится необходимость получить независимость от микшера уровня ядра и если вдруг потребуется супер - малая задержка воспроизведения или записи звука - необходимо будет перейти на уровень Kernel Streaming. Очень подробно архитектура приведена в NTDDK\help\d_stream.chm Также приложил файл = модель звуковой подсистемы. Еще есть демонстрационное приложение скачать можно отсюда http://www.microsoft.com/whdc/device/audio/DirectKS.mspx Прикреплённый файлaudio_model.PNG (7.52 Кбайт, скачиваний: 891) |
Сообщ.
#11
,
|
|
|
Цитата gena_dj @ Очень подробно архитектура приведена в NTDDK\help\d_stream.chm Спасибо, интересно. А как мне воспользоваться ссылкой на chm файл? |
Сообщ.
#12
,
|
|
|
Цитата MuratMusic @ chm - стандартный виндовый хелп-файл. А как мне воспользоваться ссылкой на chm файл? |
Сообщ.
#13
,
|
|
|
Цитата MuratMusic @ NTDDK Вероятно, сначала нужно поиметь NTDDK... Хотя бы в составе Platform SDK... |
Сообщ.
#14
,
|
|
|
Цитата Rikkie @ Цитата MuratMusic @ chm - стандартный виндовый хелп-файл.А как мне воспользоваться ссылкой на chm файл? Я имел в виду, что когда я ввожу указанную ссылку в адресную строку браузера, то ничего не получается (и не дожно наверное). Удалось выяснить, что waveOutWrite() менее зависима от версии Windows, чем способы более близкого доступа к железу звуковой карты напрямую. В общем, я до этой темы форума полагал, что waveOutWrite() и есть самая низкоуровневая Windows-функция для работы со звуком. Но для моих сегодняшних задач waveOutWrite() пока хватает. Добавлено отправил эту строчку, чтобы удалось подписаться на эту тему (поставив галочку) |
Сообщ.
#15
,
|
|
|
Цитата MuratMusic @ А как мне воспользоваться ссылкой на chm файл? http://club.shelek.com/viewfiles.php?id=2 погляди DDK для Windows 2000 |