1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
| #include "stdafx.h"
#include "windows.h"
#include "mmsystem.h"
#include "stdio.h"
#include "string.h"
#include <iostream>
using namespace std;
#pragma comment(lib, "winmm.lib")
#define BLOCK_SIZE 8000//размер отдельного блока
typedef struct//the "RIFF" chunk descriptor
{
BYTE riff[4];//четырехбуквенный код FOURCC, который идентифицирует данные, хранящиеся во фрагменте
DWORD size;// размер области данных в байтах (без учета размера самого заголовка)
BYTE wave[4];
} _WAVEDESCR;
typedef struct
{
BYTE id[4];
DWORD size;
SHORT format;// Формат звуковых данных. Мы будем использовать в основном WAVE_FORMAT_PCM
SHORT channels;//Количество каналов (1- моно, 2 - стерео).
DWORD sampleRate;//Частота дискретизации (возможны значения 8000, 11025. 22050 и 44100).
DWORD byteRate;//Количество байт в секунду. Для WAVE_FORMAT_PCM это является результатом sampleRate* blockAlign
SHORT blockAlign;//Выравнивание блока. Для WAVE_FORMAT_PCM равен bitsPerSample/8* channels
SHORT bitsPerSample;//Количество бит в одной выборке. Для WAVE_FORMAT_PCM может быть 8 или 16
} _WAVEFORMATEX;
HWAVEOUT m_hWaveout;//сюда будет записан указатель на устройство воспроизведения.
BOOL Open(SHORT channels, DWORD sampleRate, SHORT bitsPerSample)//открываем звуковое устройство
{
//передаём ему данные о формате
BOOL bResult = TRUE;
SHORT format = WAVE_FORMAT_PCM;
SHORT blockAlign = channels << 1;
WAVEFORMATEX wfex;//структуру типа WAVEFORMATEX, в которой описан формат воспроизводимых звуковых данных
wfex.wFormatTag = format;
wfex.nChannels = channels;
wfex.nSamplesPerSec = sampleRate;
wfex.nAvgBytesPerSec = blockAlign * sampleRate;
wfex.nBlockAlign = blockAlign;
wfex.wBitsPerSample = bitsPerSample;
wfex.cbSize = 0;// комментарии
//WAVE_MAPPER- звуковое устройство по умолчанию
if ( waveOutOpen(&m_hWaveout, WAVE_MAPPER, &wfex,0,0, CALLBACK_NULL) != MMSYSERR_NOERROR)//открываем звуковое устройство по умолчанию
{
m_hWaveout = NULL;
bResult = FALSE;
}
return bResult;
}
void main()
{
FILE * f;
_WAVEDESCR m_Descriptor;//дескриптор устройства
_WAVEFORMATEX m_Format;
WAVEHDR *m_WaveHeader;//динамически выделяемый массив заголовков для передачи драйверу устройства
LPBYTE *m_lpData;//массив указателей на начало каждого из блоков(делим на блоки ,чтобы не загружать на устройство сразу большой фаил)
memset(&m_Descriptor, 0, sizeof(_WAVEDESCR));//забиваем нулями
memset(&m_Format, 0, sizeof(_WAVEFORMATEX));
f=fopen("yblackbird.wav","rb");
//f=fopen("123.wav","rb"); //открываем файлик
//f=fopen("Серега - King Ring.wav","rb");
//f=fopen("amerika.wav","rb");
if ( f==0 )
{
printf("Do not open this file!!! - %s\n","123.wav");
return;
}
fread(&m_Descriptor, sizeof(_WAVEDESCR), 1, f);//загружаем дескриптор
if (strncmp((LPCSTR)m_Descriptor.wave, "WAVE", 4) == 0)// проверяем является ли наш формат wave
{
fread(&m_Format, sizeof(_WAVEFORMATEX), 1, f);
cout << "Good" << "\n";
}
if ((strncmp((LPCSTR)m_Format.id, "fmt ", 4) == 0) && (m_Format.format == 1))//находим подзаголовок "fmt "
{
BYTE id[4];
DWORD size;
fread(id, sizeof(BYTE), 4, f);//считываем его
fread(&size, sizeof(DWORD), 1, f);
cout<<"size "<<size<<"\n";
//DWORD offset = ftell(f);//Функция ftell получает текущую позицию указателя на файл
//(если он есть), связанного с потоком stream. Позиция выражается
//как смещение offset от начала потока stream.
int m(0);
m = size/BLOCK_SIZE;// находим на сколько блоков мы разобъём данные
if(m < 1)
{
m = 1;
}
m_lpData = new LPBYTE[m];//массив указателей на область в памяти для каждого блока данных
m_WaveHeader = new WAVEHDR[m] ;// массив заголовков для каждого блока данных
for(int k(0) ; k < m ; k++)
{
memset(&(m_WaveHeader[k]), 0, sizeof(WAVEHDR));// забиваем нулями
m_lpData[k] = 0;
}
int i(0);
for(DWORD readSize(0) ; ((readSize < m_Descriptor.size)&&(i<m)) ;readSize=readSize+BLOCK_SIZE)//считываем данные в блоки
{
m_lpData[i] = (LPBYTE)malloc(BLOCK_SIZE*sizeof(BYTE));// выделяем область в памяти для каждого блока
fread(m_lpData[i], sizeof(BYTE), BLOCK_SIZE, f);//считываем туда данные
m_WaveHeader[i].lpData = (LPSTR)m_lpData[i];//забиваем наши данные в заголовок
m_WaveHeader[i].dwBufferLength = BLOCK_SIZE;
m_WaveHeader[i].dwFlags = WHDR_INQUEUE;//все заголовки соссоят в очереди на устройстве
i++;
}
//--------------------------------------
if (Open(m_Format.channels, m_Format.sampleRate, m_Format.bitsPerSample))//открываем устройство
{
for(int j(0) ; j < m ; j++)
{
waveOutPrepareHeader(m_hWaveout, &(m_WaveHeader[j]), sizeof(WAVEHDR)); //отправляем j-ый заголовок на устройство
waveOutWrite(m_hWaveout, &(m_WaveHeader[j]), sizeof(WAVEHDR));//начинаем проигрывать кусочки
waveOutUnprepareHeader(m_hWaveout, &(m_WaveHeader[j]), sizeof(WAVEHDR));//отчищаем заголовок
}
}
}
waveOutClose(m_hWaveout);// закрыть драйвер
fclose(f);
} |