source: trunk/Utilities/Miscellaneous/WaveOut01/WaveOut01.cpp @ 843

Last change on this file since 843 was 843, checked in by roman, 4 years ago
  • Property svn:mime-type set to application/octet-stream
File size: 12.8 KB
Line 
1// NOTE: https://stackoverflow.com/a/49673867/868014
2
3#define _WIN32_IE 0x0500
4#define _WIN32_WINNT 0x0501
5#define WINVER _WIN32_WINNT
6
7#include <windows.h>
8#include <mmsystem.h>
9#include <commctrl.h>
10
11#include <stdint.h>
12#include <stdio.h>
13#include <math.h>
14#include <assert.h>
15
16#pragma comment(lib, "winmm.lib")
17#pragma comment(lib, "comctl32.lib")
18
19short freq, ampl;
20
21
22
23typedef struct {
24    long chnl, smpl, bits, size, swiz;
25    void *sink, *data[2];
26} WAVE;
27
28
29
30LRESULT APIENTRY WndProc(HWND hWnd, UINT uMsg, WPARAM wPrm, LPARAM lPrm) {
31    switch (uMsg) {
32        case WM_DESTROY:
33            PostQuitMessage(0);
34            return 0;
35
36        case WM_NOTIFY:
37            switch (((NMHDR*)lPrm)->idFrom) {
38                case 2:
39                    freq = ((NMUPDOWN*)lPrm)->iPos;
40                    break;
41
42                case 4:
43                    ampl = ((NMUPDOWN*)lPrm)->iPos;
44                    break;
45            }
46            return 0;
47
48        default:
49            break;
50    }
51    return DefWindowProc(hWnd, uMsg, wPrm, lPrm);
52}
53
54
55
56void FillBuf(WAVE *wave, short freq, short ampl, long *phaz) {
57    int16_t *data = (int16_t *) wave->data[wave->swiz ^= 1];
58    float tone = 1.0f * freq / wave->smpl;
59    long iter;
60
61    for(iter = 0; iter < wave->size; iter++)
62        data[iter] = ((long)(tone * (iter + *phaz)) & 1)? ampl : -ampl;
63
64    *phaz = *phaz + iter;//2.0 * frac(0.5 * tone * (iter + *phaz)) / tone;
65}
66
67
68
69DWORD APIENTRY WaveFunc(LPVOID data) 
70{
71    WAVEHDR *whdr;
72    WAVE *wave;
73    intptr_t *sink;
74    long size, phaz = 0;
75
76    wave = (WAVE*)data;
77    whdr = (WAVEHDR*)(sink = (intptr_t*) wave->sink)[1];
78    size = wave->chnl * wave->size * (wave->bits >> 3);
79
80        HWAVEOUT hWaveOut = (HWAVEOUT) sink[0];
81        HANDLE hEvent = (HANDLE)sink[2];
82
83    whdr[0].dwBufferLength = whdr[1].dwBufferLength = size;
84    whdr[0].dwFlags        = whdr[1].dwFlags        = 0;
85    whdr[0].dwLoops        = whdr[1].dwLoops        = 0;
86    whdr[0].lpData = (LPSTR)(wave->data[0] = calloc(1, size));
87    whdr[1].lpData = (LPSTR)(wave->data[1] = calloc(1, size));
88
89    ResetEvent(hEvent);
90
91        assert(wave->swiz == 0);
92    FillBuf(wave, freq, ampl, &phaz);
93    waveOutPrepareHeader(hWaveOut, &whdr[1], sizeof (WAVEHDR));
94    waveOutWrite(hWaveOut, &whdr[1], sizeof (WAVEHDR));
95
96        assert(wave->swiz == 1);
97    FillBuf(wave, freq, ampl, &phaz);
98    waveOutPrepareHeader(hWaveOut, &whdr[0], sizeof (WAVEHDR));
99    waveOutWrite(hWaveOut, &whdr[0], sizeof (WAVEHDR));
100
101        for(; ; )
102        {
103                WaitForSingleObject(hEvent, INFINITE);
104            ResetEvent(hEvent);
105                for(long index = 0; index < 2; index++)
106                        if(whdr[index].dwFlags & WHDR_DONE)
107                        {
108                                wave->swiz = index ^ 1;
109                                //waveOutUnprepareHeader(hWaveOut, &whdr[wave->swiz], sizeof (WAVEHDR));
110                                FillBuf(wave, freq, ampl, &phaz);
111                                //waveOutPrepareHeader(hWaveOut, &whdr[wave->swiz], sizeof (WAVEHDR));
112                                waveOutWrite(hWaveOut, &whdr[wave->swiz], sizeof (WAVEHDR));
113                        }
114        }
115    return 0;
116}
117
118
119
120int main() //APIENTRY WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR args, int show)
121{
122    WNDCLASSEX wndc = {sizeof(wndc), CS_HREDRAW | CS_VREDRAW, WndProc, 0, 0,
123                       NULL, //inst,
124                                                LoadIcon(0, IDI_HAND), LoadCursor(0, IDC_ARROW),
125                       (HBRUSH)(COLOR_BTNFACE + 1), 0, L"-", 0};
126    INITCOMMONCONTROLSEX icct = {sizeof(icct), ICC_STANDARD_CLASSES};
127        MSG pmsg = { };
128
129    HWND mwnd, cwnd, spin;
130    DWORD thrd;
131    WAVEFORMATEX wfmt;
132    intptr_t sink[3];
133    WAVE wave = {1, 44100, 16, 4096, 0, sink};
134
135//    AllocConsole();
136//    freopen("CONOUT$", "wb", stdout);
137
138    InitCommonControlsEx(&icct);
139    RegisterClassEx(&wndc);
140    mwnd = CreateWindowEx(0, wndc.lpszClassName, L" ",
141                          WS_OVERLAPPEDWINDOW | WS_VISIBLE,
142                          CW_USEDEFAULT, CW_USEDEFAULT, 320, 240,
143                          HWND_DESKTOP, 0, wndc.hInstance, 0);
144
145
146    cwnd = CreateWindowEx(WS_EX_CLIENTEDGE, WC_EDIT, 0, ES_AUTOHSCROLL
147                        | ES_WANTRETURN | ES_MULTILINE | ES_NUMBER | WS_CHILD
148                        | WS_VISIBLE, 10, 10, 100, 24, mwnd, (HMENU)1, 0, 0);
149    SendMessage(cwnd, EM_LIMITTEXT, 9, 0);
150    spin = CreateWindowEx(0, UPDOWN_CLASS, 0, UDS_HOTTRACK | UDS_NOTHOUSANDS
151                        | UDS_ALIGNRIGHT | UDS_SETBUDDYINT | UDS_ARROWKEYS
152                        | WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, mwnd, (HMENU)2, 0, 0);
153    SendMessage(spin, UDM_SETBUDDY, (WPARAM)cwnd, 0);
154    SendMessage(spin, UDM_SETRANGE32, (WPARAM)20, (LPARAM)22050);
155    SendMessage(spin, UDM_SETPOS32, 0, (LPARAM)(freq = 750 + 0 * 400));
156
157
158    cwnd = CreateWindowEx(WS_EX_CLIENTEDGE, WC_EDIT, 0, ES_AUTOHSCROLL
159                        | ES_WANTRETURN | ES_MULTILINE | ES_NUMBER | WS_CHILD
160                        | WS_VISIBLE, 10, 44, 100, 24, mwnd, (HMENU)3, 0, 0);
161    SendMessage(cwnd, EM_LIMITTEXT, 9, 0);
162    spin = CreateWindowEx(0, UPDOWN_CLASS, 0, UDS_HOTTRACK | UDS_NOTHOUSANDS
163                        | UDS_ALIGNRIGHT | UDS_SETBUDDYINT | UDS_ARROWKEYS
164                        | WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, mwnd, (HMENU)4, 0, 0);
165    SendMessage(spin, UDM_SETBUDDY, (WPARAM)cwnd, 0);
166    SendMessage(spin, UDM_SETRANGE32, (WPARAM)0, (LPARAM)32767);
167    SendMessage(spin, UDM_SETPOS32, 0, (LPARAM)(ampl = 7500 + 0 * 32767));
168
169
170    wfmt.wFormatTag = WAVE_FORMAT_PCM;
171    wfmt.nChannels = (WORD) wave.chnl;
172    wfmt.nSamplesPerSec = (DWORD) wave.smpl;
173    wfmt.nAvgBytesPerSec = (DWORD) (((wave.chnl * wave.bits) >> 3) * wave.smpl);
174    wfmt.nBlockAlign = (WORD) ((wave.chnl * wave.bits) >> 3);
175    wfmt.wBitsPerSample = (WORD) wave.bits;
176    wfmt.cbSize = 0;
177    sink[1] = (intptr_t)calloc(2, sizeof(WAVEHDR));
178    waveOutOpen((LPHWAVEOUT)&sink[0], WAVE_MAPPER, &wfmt,
179                 sink[2] = (intptr_t)CreateEvent(0, 1, 0, 0), 0,
180                 CALLBACK_EVENT);
181    SetThreadPriority(CreateThread(0, 0, WaveFunc, &wave, 0, &thrd),
182                      THREAD_PRIORITY_NORMAL + 0 * THREAD_PRIORITY_TIME_CRITICAL);
183
184    while (pmsg.message != WM_QUIT) {
185        if (PeekMessage(&pmsg, 0, 0, 0, PM_REMOVE)) {
186            TranslateMessage(&pmsg);
187            DispatchMessage(&pmsg);
188            continue;
189        }
190        Sleep(1);
191    }
192
193        // TODO: waveOutUnprepareHeader and thread termination
194
195    waveOutClose((HWAVEOUT)sink[0]);
196    fclose(stdout);
197    FreeConsole();
198
199    exit(pmsg.wParam);
200    return 0;
201}
Note: See TracBrowser for help on using the repository browser.