2010-03-01 Gonzalo Paniagua Javier <gonzalo@novell.com>
[mono.git] / mcs / class / System / System.Media / AudioData.cs
1
2 #if NET_2_0
3 using System;
4 using System.IO;
5 using System.Runtime.InteropServices;
6
7 namespace Mono.Audio {
8  
9 #if PUBLIC_API
10         public
11 #else
12         internal
13 #endif
14         abstract class AudioData {
15                 protected const int buffer_size = 4096;
16                 bool stopped = false;
17
18                 public abstract int Channels {
19                         get;
20                 }
21
22                 public abstract int Rate {
23                         get;
24                 }
25
26                 public abstract AudioFormat Format {
27                         get;
28                 }
29
30                 public virtual void Setup (AudioDevice dev) {
31                         dev.SetFormat (Format, Channels, Rate);
32                 }
33
34                 public abstract void Play (AudioDevice dev);
35
36                 public virtual bool IsStopped {
37                         get {
38                                 return stopped;
39                         }
40                         set {
41                                 stopped = value;
42                         }
43                 }
44         }
45
46         /*public enum WavCmpCodes {
47                 Unknown,
48                 PCM,
49                 ADPCM,
50         }*/
51
52 #if PUBLIC_API
53         public
54 #else
55         internal
56 #endif
57         class WavData : AudioData {
58                 Stream stream;
59                 short channels;
60                 ushort frame_divider;
61                 int sample_rate;
62                 int data_len = 0;
63                 AudioFormat format;
64
65                 public WavData (Stream data) {
66                         stream = data;
67                         byte[] buffer = new byte [12+32];
68                         int c = stream.Read (buffer, 0, 12 + 32);
69                         if (c != (12 + 32) || 
70                                         buffer [0] != 'R' || buffer [1] != 'I' || buffer [2] != 'F' || buffer [3] != 'F' ||
71                                         buffer [8] != 'W' || buffer [9] != 'A' || buffer [10] != 'V' || buffer [11] != 'E') {
72                                 throw new Exception ("incorrect format" + c);
73                         }
74                         if (buffer [12] != 'f' || buffer [13] != 'm' || buffer [14] != 't' || buffer [15] != ' ') {
75                                 throw new Exception ("incorrect format (fmt)");
76                         }
77                         int extra_size = buffer [16];
78                         extra_size |= buffer [17] << 8;
79                         extra_size |= buffer [18] << 16;
80                         extra_size |= buffer [19] << 24;
81                         int compression = buffer [20] | (buffer [21] << 8);
82                         if (compression != 1)
83                                 throw new Exception ("incorrect format (not PCM)");
84                         channels = (short)(buffer [22] | (buffer [23] << 8));
85                         sample_rate = buffer [24];
86                         sample_rate |= buffer [25] << 8;
87                         sample_rate |= buffer [26] << 16;
88                         sample_rate |= buffer [27] << 24;
89                         int avg_bytes = buffer [28];
90                         avg_bytes |= buffer [29] << 8;
91                         avg_bytes |= buffer [30] << 16;
92                         avg_bytes |= buffer [31] << 24;
93                         //int block_align = buffer [32] | (buffer [33] << 8);
94                         int sign_bits = buffer [34] | (buffer [35] << 8);
95                         /*Console.WriteLine (extra_size);
96                         Console.WriteLine (compression);
97                         Console.WriteLine (channels);
98                         Console.WriteLine (sample_rate);
99                         Console.WriteLine (avg_bytes);
100                         Console.WriteLine (block_align);
101                         Console.WriteLine (sign_bits);*/
102                         if (buffer [36] != 'd' || buffer [37] != 'a' || buffer [38] != 't' || buffer [39] != 'a') {
103                                 throw new Exception ("incorrect format (data)");
104                         }
105                         int sample_size = buffer [40];
106                         sample_size |= buffer [41] << 8;
107                         sample_size |= buffer [42] << 16;
108                         sample_size |= buffer [43] << 24;
109                         data_len = sample_size;
110                         //Console.WriteLine (sample_size);
111                         switch (sign_bits) {
112                         case 8:
113                                 frame_divider = 1;
114                                 format = AudioFormat.U8; break;
115                         case 16:
116                                 frame_divider = 2;
117                                 format = AudioFormat.S16_LE; break;
118                         default:
119                                 throw new Exception ("bits per sample");
120                         }
121                 }
122
123                 public override void Play (AudioDevice dev) {
124                         int read;
125                         int count = data_len;
126                         byte[] buffer = new byte [buffer_size];
127                         stream.Position = 0;
128                         while (!IsStopped && count >= 0 && (read = stream.Read (buffer, 0, System.Math.Min (buffer.Length, count))) > 0) {
129                                 // FIXME: account for leftover bytes
130                                 dev.PlaySample (buffer, read/frame_divider);
131                                 count -= read;
132                         }
133                 }
134
135                 public override int Channels {
136                         get {return channels;}
137                 }
138                 public override int Rate {
139                         get {return sample_rate;}
140                 }
141                 public override AudioFormat Format {
142                         get {return format;}
143                 }
144         }
145
146         // http://en.wikipedia.org/wiki/Au_file_format
147 #if PUBLIC_API
148         public
149 #else
150         internal
151 #endif
152         class AuData : AudioData {
153                 Stream stream;
154                 short channels;
155                 ushort frame_divider;
156                 int sample_rate;
157                 int data_len = 0;
158                 AudioFormat format;
159
160                 public AuData (Stream data) {
161                         stream = data;
162                         byte[] buffer = new byte [24];
163                         int c = stream.Read (buffer, 0, 24);
164                         if (c != 24 || 
165                                         buffer [0] != '.' || buffer [1] != 's' || buffer [2] != 'n' || buffer [3] != 'd') {
166                                 throw new Exception ("incorrect format" + c);
167                         }
168                         int data_offset = buffer [7];
169                         data_offset |= buffer [6] << 8;
170                         data_offset |= buffer [5] << 16;
171                         data_offset |= buffer [4] << 24;
172                         data_len = buffer [11];
173                         data_len |= buffer [10] << 8;
174                         data_len |= buffer [9] << 16;
175                         data_len |= buffer [8] << 24;
176                         int encoding = buffer [15];
177                         encoding |= buffer [14] << 8;
178                         encoding |= buffer [13] << 16;
179                         encoding |= buffer [12] << 24;
180                         sample_rate = buffer [19];
181                         sample_rate |= buffer [18] << 8;
182                         sample_rate |= buffer [17] << 16;
183                         sample_rate |= buffer [16] << 24;
184                         int chans = buffer [23];
185                         chans |= buffer [22] << 8;
186                         chans |= buffer [21] << 16;
187                         chans |= buffer [20] << 24;
188                         channels = (short)chans;
189                         if (data_offset < 24 || (chans != 1 && chans != 2)) {
190                                 throw new Exception ("incorrect format offset" + data_offset);
191                         }
192                         if (data_offset != 24) {
193                                 for (int l = 24; l < data_offset; ++l)
194                                         stream.ReadByte ();
195                         }
196                         switch (encoding) {
197                         case 1:
198                                 frame_divider = 1;
199                                 format = AudioFormat.MU_LAW; break;
200                         default:
201                                 throw new Exception ("incorrect format encoding" + encoding);
202                         }
203                         if (data_len == -1) {
204                                 data_len = (int)stream.Length - data_offset;
205                         }
206                         // Console.WriteLine ("format: {0}, rate: {1}", format, sample_rate);
207                 }
208
209                 public override void Play (AudioDevice dev) {
210                         int read;
211                         int count = data_len;
212                         byte[] buffer = new byte [buffer_size];
213                         stream.Position = 0;
214                         while (!IsStopped && count >= 0 && (read = stream.Read (buffer, 0, System.Math.Min (buffer.Length, count))) > 0) {
215                                 // FIXME: account for leftover bytes
216                                 dev.PlaySample (buffer, read/frame_divider);
217                                 count -= read;
218                         }
219                 }
220
221                 public override int Channels {
222                         get {return channels;}
223                 }
224                 public override int Rate {
225                         get {return sample_rate;}
226                 }
227                 public override AudioFormat Format {
228                         get {return format;}
229                 }
230         }
231
232 }
233
234 #endif
235