egra: even more comments
[iv.d.git] / follin / synth / vorbis.d
blobc0da828e7943610a8075b0e9907a021533f68c52
1 /* Invisible Vector Library
2 * coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
3 * Understanding is not required. Only obedience.
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3 of the License ONLY.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 module iv.follin.synth.vorbis /*is aliced*/;
19 import iv.alice;
20 import iv.follin.engine : TflChannel;
22 static if (__traits(compiles, () { import iv.stb.vorbis; })) {
23 import iv.stb.vorbis;
26 // ////////////////////////////////////////////////////////////////////////// //
27 class VorbisChannel : TflChannel {
28 VorbisDecoder vf;
29 // for stb
30 const(float)* left, right;
31 int hasframes; // 0: eof
32 int frused;
33 long vrtotalFrames = -666;
35 this (string fname) {
36 import core.stdc.stdio;
38 vf = new VorbisDecoder(fname);
39 if (vf.closed) {
40 import core.stdc.stdio;
41 printf("can't open file: '%.*s'\n", cast(uint)fname.length, fname.ptr);
42 vf = null;
43 return;
46 if (vf.sampleRate < 1024 || vf.sampleRate > 96000) {
47 import core.stdc.stdio;
48 printf("fucked file sample rate: '%.*s'\n", cast(uint)fname.length, fname.ptr);
49 vf.close();
50 vf = null;
51 return;
54 if (vf.chans < 1 || vf.chans > 2) {
55 import core.stdc.stdio;
56 printf("fucked file channels: '%.*s'\n", cast(uint)fname.length, fname.ptr);
57 vf.close();
58 vf = null;
59 return;
61 stereo = (vf.chans == 2);
63 sampleRate = vf.sampleRate;
64 { import core.stdc.stdio; printf("%uHz, %u channels\n", vf.sampleRate, vf.chans); }
66 hasframes = 1;
67 frused = 1; // hoax
68 vrtotalFrames = -666;
71 ~this () {}
73 override @property long totalMsecs () {
74 if (vrtotalFrames == -666) {
75 vrtotalFrames = (vf !is null ? vf.streamLengthInSamples : 0);
76 //{ import core.stdc.stdio; printf("vorbis: got %u frames\n", cast(int)vrtotalFrames); }
77 if (vrtotalFrames < 0) vrtotalFrames = -1;
79 return (vrtotalFrames >= 0 ? vrtotalFrames*1000/sampleRate : -1);
82 // `false`: no more frames
83 final bool moreFrames () nothrow {
84 if (hasframes == 0) return false;
85 if (frused >= hasframes) {
86 int haschans;
87 float** frbuffer;
88 frused = 0;
89 hasframes = vf.getFrameFloat(&haschans, &frbuffer);
90 //{ import core.stdc.stdio; printf("vorbis: got %u frames\n", hasframes); }
91 if (hasframes <= 0) { hasframes = 0; vf.close(); vf = null; return false; } // eof
92 // setup buffers
93 left = frbuffer[0];
94 right = frbuffer[haschans > 1 ? 1 : 0];
96 return true;
99 final @property uint framesLeft () nothrow @nogc { return (hasframes ? hasframes-frused : 0); }
101 override uint fillFrames (float[] buf) nothrow {
102 if (!moreFrames) return 0;
103 auto fr2put = framesLeft;
104 if (fr2put > buf.length/2) fr2put = cast(uint)(buf.length/2);
105 //{ import core.stdc.stdio; printf("vorbis: writing %u frames; follin wanted %u frames\n", fr2put, cast(uint)(buf.length/2)); }
106 frused += fr2put; // skip used frames
107 auto d = buf.ptr;
108 auto l = left;
109 auto r = right;
110 foreach (immutable _; 0..fr2put) {
111 *d++ = (*l++);
112 *d++ = (*r++);
114 left = l;
115 right = r;
116 return fr2put;