На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела "Программирование звука"
0) Данный раздел предназначен для обсуждения проблем, возникающих при программировании задач, связанных с записью, обработкой, воспроизведением звука. Перед созданием темы подумайте, не будет ли она уместнее в разделах Разработка и тестирование программ, Наши исходники, а особенно Разовые заказы и подработки
1) На Раздел распространяются все Правила форума.Огромная просьба с ними внимательно ознакомиться.
2) Запрещается давать бессмысленные ответы вроде: "Снеси Мастдай", "ХП рулит", "Поставь Линукс" и т.д.
3) Запрещается создавать темы, в которых Вы намереваетесь получить ссылку на кряки, серийники и т.п. Также запрещено любое обсуждение p2p (peer-to-peer) сетей (BitTorrent, eDonkey и т.д.).
4) Реклама всякого рода пресекается беспощадно.
5) Используйте тэг [CODE] для выделения кода программы (непременно с указанием языка программирования - выбрать из списка. В противном случае бессмысленно!). Уважайте тех, кто будет читать ваш код!
6) Если решение вашей проблемы найдено, то не забываем помечать тему специальной функцией "Вопрос решён". Вам всего лишь требуется при написании последнего ответа поставить одну единственную галочку прямо над формой ответа.
7) Если вы хотите получить совет для конкретной платформы/языка программирования, обязательно укажите их в вопросе

8) Если не прикрепляются/не скачиваются файлы, читаем Не прикрепляется / не скачивается файл. Любые обсуждения в данном разделе проблем с приложением файлов считаются оффтопиком! Со всеми вытекающими.

9) NEW! Уважаемые новички! Мы приветствуем Ваше желание научить всех посетителей раздела правильному программированию. Но огромная просьба, перед тем, как писать поучения в старых (последний ответ - "старее" месяца, а особенно, если вопрошавший не появляется на форуме уже не первый месяц, в чем можно убедиться в его профиле) темах, хорошо подумать, будет ли кому-нибудь, кроме Вас cамих, это интересно. Попытки накрутки количества тематических сообщений за счёт поднятия древних неактуальных тем ("некрофилия") будут наказываться по велению левой пятки модераторского состава (см. пп.12, 13 Правил)



Нарушение Правил может повлечь наказание со стороны модераторов.



user posted imageFAQ Раздела user posted imageПоиск в Разделе user posted imageMSDN Library Online | Ваше мнение о модераторах: user posted imageBarazuk user posted imageRikkie
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> использование waveOutWrite() , помогите обнаружить ошибку
    Здравствуйте, уважаемые программисты. Это моё первое сообщение а этом форуме.

    Пытаюсь с помощью MSDN запустить простейший вывод звука (из массива), приложение компилируется и даже запускается. Но звука нет. Предполагаю, что либо звук не тот я мысленно нарисовал в char-массиве, либо нужно программно задержаться после вызова waveOutWrite(), чтобы дать ему время прозвучать...

    ExpandedWrap disabled
      // ПРОГРАММА ТЕСТИРОВАНИЯ 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;
      }
    Сообщение отредактировано: MuratMusic -
      По-моему, данный код генерирует 22 кГц звук низкой амплитуды. Проверку работоспособности кода надо делать с помощью спец. аппаратуры. Человек не слышит звук такой частоты.
        Я переделал исходник (см. выше), теперь в цикле формирования массива используется функция rand(), чтобы получить хотя бы какое-то подобие шума. Всё равно тишина.

        Думаю, проблема может быть зарыта в том, что буфер должен быть очень коротким (десятки и сотни миллисекунд), и по всей видимости надо как-то отслеживать поведение драйвера звуковой платы (а именно прекращение воспроизведения коротенького упомянутого буфера, чтобы специальная callback-функция подкинула драйверу очередную порцию звука, т.е. очередной заранее подготовленный буфер). Только интересно бы увидеть, как это сделать в коде. Я пока не нашёл ни одного простого примера, либо примеры настолько сложны, что можно запутаться во множестве непонятных и незнакомых функций.
        Сообщение отредактировано: MuratMusic -
          Я писал плееры/рекордеры только на ВБ6. При изучении использовал этот пример от MS.
            Если Вам нужно просто выводить звук, может быть проще использовать универсальную АПИ mciSendString из библиотеки Winmm.dll

            http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_mcisendstring.asp

            ExpandedWrap disabled
              mciSendString ("open " + """ + sFiles + """ , "", %NULL, hDlg)
              mciSendString ("play " + """ + sFiles + """ + " notify", "", 0, hDlg)
               
              и когда в процедуре обработки окна получаем
              сообщение MM_MCINOTIFY проверяем что музфка отыграла по WPARAM=MCI_NOTIFY_SUCCESSFUL
               
              шлем команду закрытия
              mciSendString ("close " + """ + sFiles + """, "", %NULL, %NULL)


            хотя если простой вывод без окон то можно убрать " notify"
            тогда просто будет гудеть от начала и до конца.
              Цель - научиться пользоваться функциями именно низкоуровневого доступа к звуковой карте (waveOutWrite и т.п.).

              Эти функции мне интересны возможностью почти полного контроля над выходами/входами звуковой карты.
              Сообщение отредактировано: MuratMusic -
                Какой кайф! Заработал генератор белого шума (пока длительностью в 1 секунду, но это уже по барабану, я получил таки контроль над выходом звуковой карты!)

                Исправленный исходник для Visual C++

                ExpandedWrap disabled
                  // ПРОГРАММА ТЕСТИРОВАНИЯ 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 )
                  А вот примерно куда надо копать, чтоб не нужно было

                  Цитата MuratMusic @
                  // вообще-то MessageBox в данном случае, чтобы успеть насладиться звуком.


                  И как по уму доступаться к 16-битным самплам...

                  ExpandedWrap disabled
                    // ПРОГРАММА ТЕСТИРОВАНИЯ 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;
                    }


                  Блин, сделал еще с утра, так с предновогодней суетой не было времени кинуть...
                    Спасибо, скоро постараюсь досконально разобрать по полочкам.
                      Цитата 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)
                        Цитата gena_dj @
                        Очень подробно архитектура приведена в

                        NTDDK\help\d_stream.chm

                        Спасибо, интересно. А как мне воспользоваться ссылкой на chm файл?
                          Цитата MuratMusic @
                          А как мне воспользоваться ссылкой на chm файл?
                          chm - стандартный виндовый хелп-файл.
                            Цитата MuratMusic @
                            NTDDK


                            Вероятно, сначала нужно поиметь NTDDK... Хотя бы в составе Platform SDK... :)
                              Цитата Rikkie @
                              Цитата MuratMusic @
                              А как мне воспользоваться ссылкой на chm файл?
                              chm - стандартный виндовый хелп-файл.

                              Я имел в виду, что когда я ввожу указанную ссылку в адресную строку браузера, то ничего не получается (и не дожно наверное).

                              Удалось выяснить, что waveOutWrite() менее зависима от версии Windows, чем способы более близкого доступа к железу звуковой карты напрямую.

                              В общем, я до этой темы форума полагал, что waveOutWrite() и есть самая низкоуровневая Windows-функция для работы со звуком. Но для моих сегодняшних задач waveOutWrite() пока хватает.

                              Добавлено
                              отправил эту строчку, чтобы удалось подписаться на эту тему (поставив галочку)
                                Цитата MuratMusic @
                                А как мне воспользоваться ссылкой на chm файл?

                                http://club.shelek.com/viewfiles.php?id=2
                                погляди DDK для Windows 2000
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0455 ]   [ 15 queries used ]   [ Generated: 3.05.24, 19:49 GMT ]