Войти
ПрограммированиеФорумЗвук

DirectSound

#0
10:51, 29 окт. 2011

Добрый день!

Начал немного разбираться с DirectSound и возник небольшой вопрос.
Взять хотя бы следующую статью http://netlib.narod.ru/library/book0051/ch04_03.htm#h05.

Вопрос в том, что если мы создаем вторичный буфер с одним каналом и 16 битами на сэмпл, а потом как-нибудь хотим его заполнить, например

char *Ptr;
DWORD Size;
if(SUCCEEDED(g_pDSBuffer->Lock(0, 0, (void**)&Ptr,
            (DWORD*)&Size, NULL, 0, DSBLOCK_ENTIREBUFFER))) {
    // Произошла ошибка
}
for(long i = 0; i < Size; i++)
    Ptr = rand() % 65536;

(извините за отсутствие тегов)

то почему используется массив char? Тем более странно зачем rand() % 65536, если все равно запишется < 128 (256).
Получается, что если использовать 8 бит на сэмпл, то 1 сэмпл = 1 char, а если 16 бит, то 1 сэмпл = 2 char.

При попытке вместо char использовать short получаю вылетающую программу (вылет происходит при попытке блокировки буфера).
Неужели нужно руками разносить 1 short на 2 char?

Может быть есть какой-нибудь удобный и быстрый способ? Спасибо.


#1
13:04, 29 окт. 2011

Parsec
Там просто идёт набор данных. А по сколько извлекать, дело его. И да, тебе никто не мешает записывать хоть в буфер long long* buffer. Главное чтобы там лежали правильные данные.

#2
13:24, 29 окт. 2011

То, что там идёт набор данных я понял, вот только почему тогда программа вылетает, когда я вместо char пишу short?
Кстати, компилятор не ругается.

#3
13:27, 29 окт. 2011

Parsec
Приведи пример кода. Да и зачем писать short? Ты что сделать хочешь, пищание на определённой частоте?

#4
13:43, 29 окт. 2011
// Ch2p1_ToneGenerator.cpp : Defines the entry point for the console application.
//

#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <math.h>
#include <conio.h>

#include <dsound.h>
#include <dxerr8.h>
#include "dxutil.h"

using namespace std;
#define PI 3.14159

// global variables /////////////////////////////////////////////////////////

IDirectSound8 *g_pDS;
IDirectSoundBuffer *g_pDSPrimary;
IDirectSoundBuffer8 *g_pDSBuffer;

// code /////////////////////////////////////////////////////////////////////

HWND GetConsoleWindowHandle()
{
  char title[512];
  HWND hWnd;

  GetConsoleTitle(title, sizeof(title));
  hWnd = FindWindow(NULL, title);
  return(hWnd);
}

// InitAudio: initializes DirectX Audio
void InitAudio()
{

    if(FAILED(DirectSoundCreate8(NULL, &g_pDS, NULL)))
     {
    // Произошла ошибка
    }

    if(FAILED(g_pDS->SetCooperativeLevel(GetConsoleWindowHandle(), DSSCL_PRIORITY)))
     {
    // Произошла ошибка
    }

    DSBUFFERDESC       dsbd;         // Описание буфера

    ZeroMemory(&dsbd, sizeof(DSBUFFERDESC)); // Обнуляем структуру

    dsbd.dwSize        = sizeof(DSBUFFERDESC); // Устанавливаем размер структуры
    dsbd.dwFlags       = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME;
    dsbd.dwBufferBytes = 0;                    // Не задаем размер буфера
    dsbd.lpwfxFormat   = NULL;                 // Не задаем формат

    if  (FAILED(g_pDS->CreateSoundBuffer(&dsbd, &g_pDSPrimary, NULL)))
    {
    // Произошла ошибка
    }

    WAVEFORMATEX wfex;
    ZeroMemory(&wfex, sizeof(WAVEFORMATEX));

    wfex.wFormatTag      = WAVE_FORMAT_PCM;
    wfex.nChannels       = 1;           // моно
    wfex.nSamplesPerSec  = 22050;       // 22050 Гц
    wfex.wBitsPerSample  = 16;          // 16 бит
    wfex.nBlockAlign     = (wfex.wBitsPerSample / 8) * wfex.nChannels;
    wfex.nAvgBytesPerSec = wfex.nSamplesPerSec * wfex.nBlockAlign;

    if(FAILED(g_pDSPrimary->SetFormat(&wfex)))
    {
    // Произошла ошибка
    }

    SAFE_RELEASE( g_pDSPrimary );

}

int CreateSecondaryBuffer()
{

    IDirectSoundBuffer  *pDSB;        // Локальный звуковой буфер

    // Инициализируем структуру WAVEFORMATEX

    WAVEFORMATEX wfex;
    ZeroMemory(&wfex, sizeof(WAVEFORMATEX));

    wfex.wFormatTag      = WAVE_FORMAT_PCM;
    wfex.nChannels       = 1;        // моно
    wfex.nSamplesPerSec  = 22050;    // 22050 Гц
    wfex.wBitsPerSample  = 16;       // 16 бит
    wfex.nBlockAlign     = (wfex.wBitsPerSample / 8) * wfex.nChannels;
    wfex.nAvgBytesPerSec = wfex.nSamplesPerSec * wfex.nBlockAlign;

    // Инициализируем структуру DSBUFFERDESC
    DSBUFFERDESC dsbd;
    ZeroMemory(&dsbd, sizeof(DSBUFFERDESC)); // Обнуляем структуру

    dsbd.dwSize        = sizeof(DSBUFFERDESC); // Задаем размер
    dsbd.dwFlags       = DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLPAN;
    dsbd.dwBufferBytes = wfex.nAvgBytesPerSec * 2; // 2 секунды
    dsbd.lpwfxFormat   = &wfex;

    // Создаем первую версию объекта
    if (FAILED(g_pDS->CreateSoundBuffer(&dsbd, &pDSB, NULL)))
    {
    // Произошла ошибка
    }
    else
    {
        // Получаем 8 версию интерфейса
        if(FAILED(pDSB->QueryInterface(IID_IDirectSoundBuffer8, (void**)&g_pDSBuffer)))
        {
        // Произошла ошибка - прежде чем делать
        // что-либо еще освобождаем первый интерфейс
        pDSB->Release();
        }
        else
        {
        // Освобождаем исходный интерфейс - все успешно!
        pDSB->Release();
        }
    }

}

void FillBuffer()
{

    short *Ptr;
    DWORD Size;

    if (SUCCEEDED(g_pDSBuffer->Lock(0, 0, (void**)&Ptr, (DWORD*)&Size, NULL, 0, DSBLOCK_ENTIREBUFFER)))
     {
    // Произошла ошибка
    }

    for (long i = 0; i < Size; i++)
    Ptr[i] = rand() % 65536;

    ofstream fout("D:/myfile.txt");
    for (long i = 0; i < Size; i++)
    {
        fout << (int) Ptr[i] << " ";
    }
    fout.close();

    if(FAILED(g_pDSBuffer->Unlock((void*)Ptr, Size, NULL, 0)))
    {
    // Произошла ошибка
    }

}

void PlayBuffer()
{

    if(SUCCEEDED(g_pDSBuffer->SetCurrentPosition(0)))
    {
        if(FAILED(g_pDSBuffer->Play(0,0,0)))
        {
        // Произошла ошибка
        }
    }

}

void StopBuffer()
{

    if(FAILED(g_pDSBuffer->Stop()))
    {
    // Произошла ошибка
    }

}

int main(int argc, char* argv[])
{

    InitAudio();
    CreateSecondaryBuffer();
    FillBuffer();

    PlayBuffer();
    getch();
    StopBuffer();

    return(0);

}

Почему пищание? short - 2 байта целое

#5
21:24, 30 окт. 2011

Вопрос решён.

#6
11:17, 10 янв. 2012

Parsec
> Вопрос решён.
Как? отпишись, ведь интересно же.

ПрограммированиеФорумЗвук

Тема в архиве.