Ik heb problemen met de opbouw van een stuk code dat geluid sampelt met de waveIn API. Ik gebruik CALLBACK_WINDOW om te reageren op binnenkomende data. Het is nog belangrijk om te vermelden dat waveInReset de invoer stopzet en alle huidige buffers leeg laat terugkomen.
Wat ik nu heb (vereenvoudigd):
Het probleem ontstaat als de gebruiker iets doet (bijvoorbeeld de bitrate aanpassen) waardoor de sampler wordt gestopt en onmiddelijk weer wordt gestart. Mijn applicatie zou dan moeten wachten met herstarten tot het stoppen is voltooid, dwz totdat alle lege buffers zijn teruggekomen via een Windows Message. Momenteel loopt dat door elkaar (waveInStart wordt gecalled voordat de lege buffers terug zijn) wat voor problemen zorgt.
Hoe moet ik dit nou netjes opzetten? Ik zou met wat boolean flags kunnen werken (starting, restarting, stopping, etc), maar mijn ervaring is dat dat snel een rommeltje wordt. Ik denk dat de netste oplossing is om met threads te werken, maar dan krijg ik problemen met data access.
Kunnen jullie me de goede kant op sturen?
Wat ik nu heb (vereenvoudigd):
C#: Form1
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
| private WaveInSampler sampler = new WaveInSampler(...); protected override void WndProc(ref Message m) { switch (m.Msg) { case WinAudio.MM_WIM_OPEN: Console.WriteLine("WaveIn device opened."); break; case WinAudio.MM_WIM_CLOSE: Console.WriteLine("WaveIn device closed."); break; case WinAudio.MM_WIM_DATA: sampler.handleData(m); break; default: base.WndProc(ref m); break; } } private void Start() { Stop(); sampler.start(); } private void Stop() { sampler.stop(); } |
C#: WaveInSampler
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
| private List<Buffer> buffers = new List<Buffer>(); public void start() { // Open the specified waveIn device WinAudio.waveInOpen(..., WinAudio.CALLBACK_WINDOW); // Start recording. Notice nothing will actually happen // as long as no buffer is supplied to the device. WinAudio.waveInStart(hwavein); running = true; // Add first buffers addBuffer(hwavein); addBuffer(hwavein); } public void stop() { if (running) { WinAudio.waveInReset(hwavein); clearAllBuffers(); WinAudio.waveInClose(hwavein); running = false; } } private void addBuffer(IntPtr hwave) { //Don't create a new buffer if not running anymore if (!running) return; Buffer buf = new Buffer(...); buffers.Add(buf); } public void handleData(Message m) { if (running) { // immediately add a new buffer addBuffer(hwavein); // received buffer must be first in the list Buffer buf = buffers[0]; // process buffer only if its filled properly if (buf.complete) { // do stuff } buf.Dispose(); buffers.RemoveAt(0); } else { // Empty buffer returned by waveInReset function... ignore } } ~WaveInSampler() { stop(); } |
Het probleem ontstaat als de gebruiker iets doet (bijvoorbeeld de bitrate aanpassen) waardoor de sampler wordt gestopt en onmiddelijk weer wordt gestart. Mijn applicatie zou dan moeten wachten met herstarten tot het stoppen is voltooid, dwz totdat alle lege buffers zijn teruggekomen via een Windows Message. Momenteel loopt dat door elkaar (waveInStart wordt gecalled voordat de lege buffers terug zijn) wat voor problemen zorgt.
Hoe moet ik dit nou netjes opzetten? Ik zou met wat boolean flags kunnen werken (starting, restarting, stopping, etc), maar mijn ervaring is dat dat snel een rommeltje wordt. Ik denk dat de netste oplossing is om met threads te werken, maar dan krijg ik problemen met data access.
Kunnen jullie me de goede kant op sturen?