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