Libraryless. Click here for Pure Java version (3021L/20K).
1 | // TODO: copy buffers less (have multiple listeners keep buffers without copying) |
2 | |
3 | static recordToAudioListeners_AudioLoop recordToAudioListeners(L<VF1<short[]>> audioListeners, int bufSize, SimpleLiveValue<Float> lvVolume) { |
4 | recordToAudioListeners_AudioLoop loop = new(bufSize); |
5 | loop.audioListeners = audioListeners; |
6 | loop.lvVolume = lvVolume; |
7 | ret loop; |
8 | } |
9 | |
10 | static recordToAudioListeners_AudioLoop recordToAudioListeners(L<VF1<short[]>> audioListeners, int bufSize, SimpleLiveValue<Float> lvVolume, AudioFormat quality) { |
11 | recordToAudioListeners_AudioLoop loop = new(bufSize, quality); |
12 | loop.audioListeners = audioListeners; |
13 | loop.lvVolume = lvVolume; |
14 | ret loop; |
15 | } |
16 | |
17 | sclass recordToAudioListeners_AudioLoop extends Thread implements AutoCloseable { |
18 | TargetDataLine line; |
19 | new Flag stopFlag; |
20 | byte[] buf; |
21 | short[] convertedBuf; |
22 | L<VF1<short[]>> audioListeners; |
23 | SimpleLiveValue<Float> lvVolume; |
24 | AudioFormat quality; |
25 | bool cloneDataOnce; |
26 | bool verbose; |
27 | O currentListener; // who is holding up audio processing |
28 | |
29 | *(int bufSize) { |
30 | this(bufSize, javaSound_cdQuality()); |
31 | } |
32 | |
33 | *(int bufSize, AudioFormat *quality) { |
34 | line = javaSound_recordLine(quality, bufSize); |
35 | buf = new byte[bufSize]; |
36 | convertedBuf = new short[bufSize/2]; |
37 | } |
38 | |
39 | public void start { line.start°; super.start°; } |
40 | void stopRecording { // "stop()" was taken |
41 | if (stopFlag.isUp()) ret; |
42 | stopFlag.raise°; line.close°; |
43 | print("Audio input loop stopped."); |
44 | } |
45 | public void close { stopRecording(); } |
46 | |
47 | public void run° { |
48 | print("Audio input loop started. Buffer size=" + l(buf) + " (" + iround(l(buf)/quality.getSampleRate()/quality.getFrameSize()*1000) + " ms)"); |
49 | |
50 | while (licensed() && !stopFlag.isUp()) { |
51 | int n = line.read(buf, 0, l(buf)); |
52 | if (stopFlag.isUp()) break; |
53 | if (n < l(buf)) print("Weird: Got less than a buffer: " + n + "/" + l(buf)); |
54 | if (n == 0) ret with print("EMERGENCY STOP."); |
55 | handleData(buf, n); |
56 | } |
57 | } |
58 | |
59 | void handleData(byte[] data, int n) { |
60 | if (verbose) printWithMilliseconds("Handling audio data (" + nBytes(n) + ")"); |
61 | pcall { |
62 | bytesToShorts_littleEndian(data, convertedBuf, n); |
63 | short[] convertedData = subShortArray(convertedBuf, 0, n/2); |
64 | lvSet(lvVolume, shortSamplesToPercentVolume(convertedData)); |
65 | |
66 | if (cloneDataOnce) |
67 | convertedData = cloneShortArray(convertedData); |
68 | |
69 | for i over audioListeners: { // synchro-safe, garbage-free iteration |
70 | VF1<short[]> l = syncGet(audioListeners, i); |
71 | continue if l == null; |
72 | try { |
73 | currentListener = l; |
74 | pcallF(l, convertedData); |
75 | } finally { |
76 | currentListener = null; |
77 | } |
78 | } |
79 | } |
80 | if (verbose) printWithMilliseconds("Done handling audio data"); |
81 | } |
82 | } |
download show line numbers debug dex old transpilations
Travelled to 14 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, irmadwmeruwu, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt, xrpafgyirdlv
No comments. add comment
Snippet ID: | #1018247 |
Snippet name: | recordToAudioListeners |
Eternal ID of this version: | #1018247/17 |
Text MD5: | 7aaf5ab1917939b27358baec0eb36a94 |
Transpilation MD5: | 18e80dd45e2e973d0c339faac4ce805f |
Author: | stefan |
Category: | javax / audio |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2020-02-15 14:03:10 |
Source code size: | 2880 bytes / 82 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 452 / 574 |
Version history: | 16 change(s) |
Referenced in: | [show references] |