На главную Наши проекты:
Журнал   ·   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
  
> Генерация 16-битной синусоиды в DirectSound
    Переписал пример из книжки. Он работает для звука 8-ми битного звука. Попытался сделать звук 16-битным и начались проблемы. Вот код:
    ExpandedWrap disabled
      LPDIRECTSOUND8 DS = NULL;
       
      HWND GetConsoleWindowHandle()
      {
        char title[512];
        GetConsoleTitle(title, sizeof(title));
        return FindWindow(NULL, title);
      }
       
      void InitAudio(int bitsPerSample, int samplesPerSec)
      {
          HRESULT hr;
          stringstream error;
       
          //Шаг 1: создание интерфейса DirectSound (выбираем устройство по умолчанию)
          hr = DirectSoundCreate8(NULL, &DS, NULL);
          if (FAILED(hr))
          {
              error << "DirectSoundCreate8 error: " << DXGetErrorString8(hr) << endl;
              throw (error.str());
          }
       
          //Шаг 2: создание уровня кооперации
          hr = DS->SetCooperativeLevel(GetConsoleWindowHandle(), DSSCL_PRIORITY);
          if (FAILED(hr))
          {
              error << "SetCooperativeLevel error: " << DXGetErrorString8(hr) << endl;
              throw (error.str());
          }
          
       
          //Шаг 3: Создание первичного буфера
          LPDIRECTSOUNDBUFFER primary = NULL;
       
          DSBUFFERDESC dsbd;
          ZeroMemory(&dsbd, sizeof(DSBUFFERDESC));    
          dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
          dsbd.dwSize = sizeof(DSBUFFERDESC);
          dsbd.dwBufferBytes = 0;
          dsbd.lpwfxFormat = NULL;
       
          hr = DS->CreateSoundBuffer(&dsbd, &primary, NULL);
          if (FAILED(hr))
          {
              error << "CreateSoundBuffer error (primary buffer): " <<
                  DXGetErrorString8(hr) << endl;
              throw error.str();
          }
       
          //Задаём формат первичного буфера
          WAVEFORMATEX wfx;
          ZeroMemory(&wfx, sizeof(WAVEFORMATEX));
          wfx.wFormatTag = WAVE_FORMAT_PCM;
          wfx.nChannels = (WORD)1;
          wfx.nSamplesPerSec = samplesPerSec;
          wfx.wBitsPerSample = (WORD)bitsPerSample;
          wfx.nBlockAlign = (WORD)(wfx.wBitsPerSample * wfx.nChannels / 8);
          wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
       
          hr = primary->SetFormat(&wfx);
          if (FAILED(hr))
          {
              error << "SetFormat error: " << DXGetErrorString8(hr) << endl;
              throw error.str();
          }
       
          //primary больше не нужен
          SAFE_RELEASE(primary);
      }
       
       
      int CreateSecondaryBuffer(LPDIRECTSOUNDBUFFER *buffer, int secs,
                                int samplerate, int bitspersample, DWORD flags)
      {
          HRESULT hr;
          stringstream error;
       
          DSBUFFERDESC dsbd;
          WAVEFORMATEX wfx;
       
          ZeroMemory(&wfx, sizeof(WAVEFORMATEX));
          wfx.wFormatTag = WAVE_FORMAT_PCM;
          wfx.nChannels = 1;
          wfx.nSamplesPerSec = samplerate;
          wfx.wBitsPerSample = bitspersample;
          wfx.nBlockAlign = (WORD)(wfx.wBitsPerSample * wfx.nChannels / 8);
          wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
       
          ZeroMemory(&dsbd, sizeof(DSBUFFERDESC));
          dsbd.dwSize = sizeof(DSBUFFERDESC);
          dsbd.dwFlags = flags;
          dsbd.dwBufferBytes = samplerate * bitspersample * 1 * secs / 8;
          dsbd.guid3DAlgorithm = GUID_NULL;
          dsbd.lpwfxFormat = &wfx;
       
          hr = DS->CreateSoundBuffer(&dsbd, buffer, NULL);
          if (FAILED(hr))
          {
              error << "CreateSoundBuffer error (secondary buffer): " <<
                  DXGetErrorString8(hr) << endl;
              throw error.str();
          }
       
          //Возвращаем размер буфера
          return dsbd.dwBufferBytes;
      }
       
      void FillBuffer(LPDIRECTSOUNDBUFFER buffer, float freq, int size, int samplerate, int bitsPerSample)
      {
          HRESULT hr;
          stringstream error;
          unsigned char *bufferBytes;
          DWORD lockedSize;
       
          //Запираем буфер
          hr = buffer->Lock(0, size, (void **)(&bufferBytes), &lockedSize, NULL, NULL, 0L);
          if (FAILED(hr))
          {
              error << "Lock error: " << DXGetErrorString8(hr) << endl;
              throw error.str();
          }
       
          for (DWORD q = 0; q < lockedSize; q++)
          {
              //Определяем цикл, в котором находимся
              float pos = freq / (float)samplerate * (float)q;
              //Берём остаток и переводим в радианы
              float r = (pos - floor(pos)) * 2 * PI;
              float value = sin(r);
              //Получили значение в диапазоне [-1; 1]. Умножаем на 127 и прибавляем 127,
              //чтобы получить значение в диапазоне [0; 256]
       
              bufferBytes[q] = (value * 127 + 127) / 8;
              //float k = pow((float)2, bitsPerSample)/2;
              //bufferBytes[q] = (value * k + k) / 8;
          }
          //Отпираем буфер
          buffer->Unlock(bufferBytes, lockedSize, NULL, 0);
      }
       
      void PlayBuffer(LPDIRECTSOUNDBUFFER buffer)
      {
          buffer->Play(0, 0, DSBPLAY_LOOPING);
      }
       
      void main(int argc, char* argv[])
      {
          LPDIRECTSOUNDBUFFER DsBuffer;
       
          int BitsPerSample = 16;
          int SamplesPerSec = 44100;
       
          try
          {
              cout << endl << "Tone Generator. Version 1.0" << endl << endl;
              cout << "Initializing DirectSound..." << endl;
              InitAudio(BitsPerSample, SamplesPerSec);
              cout << "Creating sound buffer..." << endl;
              int bufferSize = CreateSecondaryBuffer(&DsBuffer, 1, SamplesPerSec, BitsPerSample, 0);
              cout << "Fill buffer with data..." << endl;
              FillBuffer(DsBuffer, 440.0, bufferSize, SamplesPerSec, BitsPerSample); //440 Гц - "Ля" первой октавы
              cout << "Now playing... (press ant key to exit)" << endl;
              PlayBuffer(DsBuffer);
              getch();
       
              DsBuffer->Stop();
              cout << "Releasing sound buffer..." << endl;
              SAFE_RELEASE(DsBuffer);
              cout << "Un-initializing DirectSound..." << endl;
              SAFE_RELEASE(DS);
          }
          catch(string error)
          {
              cout << error << endl;
              getch();
              exit(-1);
          }
      }

    Для 16-битного звука, насколько я понимаю, нужно unsigned char *bufferBytes сменить на unsigned short. После этого появляется Access Violation на строчке
    ExpandedWrap disabled
      bufferBytes[q] = (value * 127 + 127) / 8;

    Появилось предположение, что unsigned short занимает в 2 раза больше места, чем unsigned char, и я попробовал вместо size передавать size*2 в Lock(). Но Lock начал жаловаться на плохой параметр. Как вывести 16-битный моно-звук с заданной частотой?
      Цитата zlib @
      Появилось предположение, что unsigned short занимает в 2 раза больше места, чем unsigned char


      Ужас... Не зная даже базовых типов данных, пытаться программировать под DirectX... :wall: Куда мы идем...

      Меняем:

      Цитата zlib @
      unsigned char *bufferBytes;


      на

      ExpandedWrap disabled
          signed short *bufferBytes;


      Цитата zlib @
      for (DWORD q = 0; q < lockedSize; q++)


      на

      ExpandedWrap disabled
            for (DWORD q = 0; q < lockedSize / 2; q++)


      и

      Цитата zlib @
      bufferBytes[q] = (value * 127 + 127) / 8;


      на

      ExpandedWrap disabled
                bufferBytes[q] = value * 32767 / 8;


      И в дальнейшем рекомендую не выдергивать сырцы из середины книжки, а читать ёё внимательно сначала. А перед этим прочесть что-нить просто по С++, для общего развития.
        Спасибо.
        Книжка была для американцев, поэтому в ней мало что объяснялось по-человечески (МакКаски "Звук в играх. Технологии программирования").
          вроде даже проще можно реализовать... еще бы разобраться какой минимально-безглючный размер у буффера :\
          ExpandedWrap disabled
            #include "dsound.h"
            #include <math.h>
            #include <stdio.h>
             
            #define PI   3.14159265359
             
            LPDIRECTSOUND DS = NULL;
             
            int InitAudio(LPDIRECTSOUNDBUFFER *buffer, int secs,
                                      int samplerate, int bitspersample)
            {
                WAVEFORMATEX wfx;
                DSBUFFERDESC dsbd;
             
                ZeroMemory(&wfx, sizeof(WAVEFORMATEX));
                wfx.wFormatTag = WAVE_FORMAT_PCM;
                wfx.nChannels = 1;
                wfx.nSamplesPerSec = samplerate;
                wfx.wBitsPerSample = bitspersample;
                wfx.nBlockAlign = (WORD)(wfx.wBitsPerSample * wfx.nChannels / 8);
                wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
             
                ZeroMemory(&dsbd, sizeof(DSBUFFERDESC));
                dsbd.dwSize = sizeof(DSBUFFERDESC);
                dsbd.dwFlags = DSBCAPS_GLOBALFOCUS;
                dsbd.dwBufferBytes = samplerate * secs;
                dsbd.lpwfxFormat = &wfx;
             
                DirectSoundCreate(NULL, &DS, NULL);
                DS->SetCooperativeLevel(GetForegroundWindow(), DSSCL_PRIORITY);
                DS->CreateSoundBuffer(&dsbd, buffer, NULL);
                //Возвращаем размер буфера
                return dsbd.dwBufferBytes;
            }
             
            void FillBuffer(LPDIRECTSOUNDBUFFER buffer, float freq, int size, int samplerate, int bitsPerSample)
            {
                short *bufferBytes;
                DWORD lockedSize;
                //Запираем буфер
                buffer->Lock(0, size, (void **)(&bufferBytes), &lockedSize, NULL, NULL, 0L);
             
                for (DWORD q = 0; q < lockedSize / 2; q++)
                {
                    //Определяем цикл, в котором находимся
                    float pos = freq / (float)samplerate * (float)q;
                    //Берём остаток и переводим в радианы
                    float r = (pos - floor(pos)) * 2 * PI;
                    float value = sin(r);
             
                    bufferBytes[q] = value * 32767 / 8;
                }
                //Отпираем буфер
                buffer->Unlock(bufferBytes, lockedSize, NULL, 0);
            }
             
            void main(int argc, char* argv[])
            {
                LPDIRECTSOUNDBUFFER DsBuffer;
             
                int BitsPerSample = 16;
                int SamplesPerSec = 48000;
             
                int bufferSize = InitAudio(&DsBuffer, 1, SamplesPerSec, BitsPerSample);
                    printf ("Creating %d bytes sound buffer \n",bufferSize);
                    printf ("Fill buffer with data...\n");//, bufferSize);
                    FillBuffer(DsBuffer, 440.0, bufferSize, SamplesPerSec, BitsPerSample);
                    //440 Гц - "Ля" первой октавы
                    printf ("Now playing... (press ant key to exit) \n");
                    DsBuffer->Play(0, 0, DSBPLAY_LOOPING);
                    getchar();
                    DsBuffer->Stop();
                    printf ("Free DirectSound...\n");
                    DsBuffer->Release();
                    DS->Release();
            }


          Добавлено
          хм.. вроде со значением равным
          Цитата

          dsbd.dwBufferBytes = 2400;//samplerate * secs;

          звучит без лагов.. это гуд :rolleyes: разобраться бы еще как на ходу WAVE генерировать :)
            Акак это можна сделать в Буилдере????
              Цитата VCJ @
              Акак это можна сделать в Буилдере????
              Это в раздел, посвященный Borland C++ Builder
              0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
              0 пользователей:


              Рейтинг@Mail.ru
              [ Script execution time: 0,0639 ]   [ 15 queries used ]   [ Generated: 27.04.24, 11:03 GMT ]