Mercurial > pmdwin
comparison wave_out.c @ 0:c55ea9478c80
Hello Gensokyo!
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Tue, 21 May 2013 10:29:21 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:c55ea9478c80 |
---|---|
1 #include <windows.h> | |
2 #include <mmsystem.h> | |
3 #include <stdio.h> | |
4 #include <stdint.h> | |
5 | |
6 /* | |
7 * some good values for block size and count | |
8 */ | |
9 #define BLOCK_SIZE 8192 | |
10 #define BLOCK_COUNT 16 | |
11 | |
12 /* | |
13 * module level variables | |
14 */ | |
15 static WAVEHDR* waveBlocks; | |
16 volatile int waveFreeBlockCount; | |
17 static int waveCurrentBlock; | |
18 | |
19 static int xaddl(int volatile *atomic, int add) | |
20 { | |
21 int val; /* This works for the 486 and later */ | |
22 __asm__ __volatile__("lock; xaddl %0, %1" | |
23 : "=r" (val), "+m" (*atomic) | |
24 : "m" (*atomic), "0" (add)); | |
25 return val; | |
26 } | |
27 | |
28 void CALLBACK waveOutProc(HWAVEOUT hWaveOut, UINT uMsg, DWORD dwInstance, DWORD dwParam1,DWORD dwParam2){ | |
29 /* | |
30 * pointer to free block counter | |
31 */ | |
32 int* freeBlockCounter = (int*)dwInstance; | |
33 /* | |
34 * ignore calls that occur due to openining and closing the | |
35 * device. | |
36 */ | |
37 if(uMsg != WOM_DONE) | |
38 return; | |
39 xaddl(freeBlockCounter, 1); | |
40 } | |
41 | |
42 static WAVEHDR* allocateBlocks(unsigned int size, unsigned int count){ | |
43 unsigned char* buffer; | |
44 int i; | |
45 WAVEHDR* blocks; | |
46 DWORD totalBufferSize = (size + sizeof(WAVEHDR)) * count; | |
47 /* | |
48 * allocate memory for the entire set in one go | |
49 */ | |
50 if((buffer = VirtualAlloc(NULL, totalBufferSize, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE)) == NULL) { | |
51 return NULL; | |
52 } | |
53 /* | |
54 * and set up the pointers to each bit | |
55 */ | |
56 blocks = (WAVEHDR*)buffer; | |
57 buffer += sizeof(WAVEHDR) * count; | |
58 for(i = 0; i < count; i++) { | |
59 blocks[i].dwBufferLength = size; | |
60 blocks[i].lpData = (char*)buffer; | |
61 buffer += size; | |
62 } | |
63 return blocks; | |
64 } | |
65 | |
66 void writeAudio(HWAVEOUT hWaveOut, short *data, unsigned int size){ | |
67 WAVEHDR* current; | |
68 int remain; | |
69 current = &waveBlocks[waveCurrentBlock]; | |
70 while(size > 0) { | |
71 /* | |
72 * first make sure the header we're going to use is unprepared | |
73 */ | |
74 if(current->dwFlags & WHDR_PREPARED) | |
75 waveOutUnprepareHeader(hWaveOut, current, sizeof(WAVEHDR)); | |
76 if(size < (int)(BLOCK_SIZE - current->dwUser)) { | |
77 memcpy(current->lpData + current->dwUser, data, size); | |
78 current->dwUser += size; | |
79 break; | |
80 } | |
81 remain = BLOCK_SIZE - current->dwUser; | |
82 memcpy(current->lpData + current->dwUser, data, remain); | |
83 size -= remain; | |
84 data += remain; | |
85 current->dwBufferLength = BLOCK_SIZE; | |
86 waveOutPrepareHeader(hWaveOut, current, sizeof(WAVEHDR)); | |
87 waveOutWrite(hWaveOut, current, sizeof(WAVEHDR)); | |
88 xaddl(&waveFreeBlockCount, -1); | |
89 | |
90 while(!waveFreeBlockCount) | |
91 Sleep(10); | |
92 | |
93 waveCurrentBlock++; | |
94 waveCurrentBlock %= BLOCK_COUNT; | |
95 current = &waveBlocks[waveCurrentBlock]; | |
96 current->dwUser = 0; | |
97 } | |
98 } | |
99 | |
100 unsigned int wave_out_open(HWAVEOUT *hWaveOut, unsigned int sfreq, unsigned char channels) { | |
101 WAVEFORMATEX wfx; | |
102 waveBlocks = allocateBlocks(BLOCK_SIZE, BLOCK_COUNT); | |
103 waveFreeBlockCount = BLOCK_COUNT; | |
104 waveCurrentBlock= 0; | |
105 if(waveBlocks == NULL) { | |
106 return MMSYSERR_NOMEM; | |
107 } | |
108 wfx.nSamplesPerSec = sfreq; | |
109 wfx.wBitsPerSample = 16; | |
110 wfx.nChannels = channels; | |
111 wfx.cbSize = 0; | |
112 wfx.wFormatTag = WAVE_FORMAT_PCM; | |
113 wfx.nBlockAlign = (wfx.wBitsPerSample * wfx.nChannels) >> 3; | |
114 wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec; | |
115 return waveOutOpen(hWaveOut, WAVE_MAPPER, &wfx, (DWORD_PTR)waveOutProc, (DWORD_PTR)&waveFreeBlockCount, CALLBACK_FUNCTION); | |
116 } | |
117 | |
118 void wave_out_close(HWAVEOUT hWaveOut) { | |
119 int i; | |
120 while(waveFreeBlockCount < BLOCK_COUNT) | |
121 Sleep(10); | |
122 | |
123 for(i = 0; i < waveFreeBlockCount; i++) | |
124 if(waveBlocks[i].dwFlags & WHDR_PREPARED) | |
125 waveOutUnprepareHeader(hWaveOut, &waveBlocks[i], sizeof(WAVEHDR)); | |
126 VirtualFree(waveBlocks, 0, MEM_RELEASE); | |
127 waveOutClose(hWaveOut); | |
128 } | |
129 |