1 /**
2  * Copyright: Copyright Auburn Sounds 2016
3  * License:   $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
4  * Authors:   Guillaume Piolat
5  */
6 module dplug.audio.sound;
7 
8 
9 /**
10  *  This module defines the interfaces that describe a "sound".
11  *  A sound is a multi-channel concept, that can be combined like input-range.
12  *  Can represent a buffer, an audio processing block, a sound sample.
13  *  For now they only deal with float.
14  */
15 enum isSound(S) = true; // All Sound capabilities are optional!
16 
17 
18 /// Duration.
19 /// A sound can optionally have a duration.
20 template hasDuration(S)
21 {
22     enum bool hasDuration = is(typeof(
23     (inout int = 0)
24     {
25         S s = S.init;
26         int d = s.duration;
27     }));
28 }
29 
30 /// Is this duration a static property?
31 template hasStaticDuration(S)
32 {
33     enum bool hasStaticDuration = hasDuration!S && __traits(compiles, int[S.duration]);
34 }
35 
36 /// Is this duration a runtime property?
37 enum bool hasRuntimeDuration(S) = !hasStaticDuration!S;
38 
39 unittest
40 {
41     struct Yes
42     {
43         enum duration = 128;
44     }
45     static assert(hasStaticDuration!Yes);
46     static assert(!hasRuntimeDuration!Yes);
47 
48     struct No
49     {
50         int duration = 128;
51     }
52     static assert(!hasStaticDuration!No);
53     static assert(hasRuntimeDuration!Yes);
54 }
55 
56 
57 /// Number of channels.
58 // A sound can optionally have a duration field.
59 template hasDuration(S)
60 {
61     enum bool hasDuration = is(typeof(
62     (inout int = 0)
63     {
64         S s = S.init;
65         int d = s.duration;
66     }));
67 }
68 
69 /// Is this duration a static property?
70 template hasStaticDuration(S)
71 {
72     enum bool hasStaticDuration = hasDuration!S && __traits(compiles, int[S.duration]);
73 }
74 
75 /// Is this duration a runtime property?
76 enum bool hasRuntimeDuration(S) = !hasStaticDuration!S;
77 
78 
79 
80 
81 /// A Sound can optionally process sample with a `nextSample` function.
82 template hasProcessSample(S)
83 {
84     enum bool hasProcessSample = is(typeof(S.init.processSample));
85 }
86 
87 /// A Sound can optionally process sample with a `nextBuffer` function.
88 template hasProcessBuffer(S)
89 {
90     enum bool hasProcessBuffer = is(typeof(S.init.processSample));
91 }
92 
93 
94 
95 
96 
97 
98 
99 /+
100 
101 /// Renders the sound into an array slice.
102 void renderToSlice(S)(auto ref S sound, float[] outBuffer) if (isSound!S)
103 {
104     // Must be mono
105     static assert(sound.channels == 1);
106 
107     // TODO: allow to render to static array if
108     static if (hasDuration!D)
109         assert(outBuffer.length == sound.duration);
110 
111     static if (hasProcessSample)
112 
113 }
114 
115 float{ubyte[] toPNG(SRC)(auto ref SRC src)
116     if (isView!SRC)
117 {
118 
119 
120  enum isView(T) =
121     is(typeof(T.init.w) : size_t) && // width
122     is(typeof(T.init.h) : size_t) && // height
123     is(typeof(T.init[0, 0])     );   // color information
124 
125 /// Returns the color type of the specified view.
126 /// By convention, colors are structs with numeric
127 /// fields named after the channel they indicate.
128 alias ViewColor(T) = typeof(T.init[0, 0]);
129 
130 /// Views can be read-only or writable.
131 enum isWritableView(T) =
132     isView!T &&
133     is(typeof(T.init[0, 0] = ViewColor!T.init));
134 
135 /// Optionally, a view can also provide direct pixel
136 /// access. We call these "direct views".
137 enum isDirectView(T) =
138     isView!T &&
139 is(typeof(T.init.scanline(0)) : ViewColor!T[]);
140 
141 +/