4 using System.Runtime.InteropServices;
13 abstract class AudioData {
14 protected const int buffer_size = 4096;
17 public abstract int Channels {
21 public abstract int Rate {
25 public abstract AudioFormat Format {
29 public virtual void Setup (AudioDevice dev) {
30 dev.SetFormat (Format, Channels, Rate);
33 public abstract void Play (AudioDevice dev);
35 public virtual bool IsStopped {
45 /*public enum WavCmpCodes {
56 class WavData : AudioData {
65 public WavData (Stream data) {
67 byte[] buffer = new byte [12 + 32];
70 // Read Chunk ID + Format
71 int c = stream.Read (buffer, 0, 12);
73 buffer [0] != 'R' || buffer [1] != 'I' || buffer [2] != 'F' || buffer [3] != 'F' ||
74 buffer [8] != 'W' || buffer [9] != 'A' || buffer [10] != 'V' || buffer [11] != 'E') {
75 throw new Exception ("incorrect format" + c);
78 // Read SubChunk 1 ID + Size => Must be 'fmt ' !
79 c = stream.Read (buffer, 0, 8);
80 if (c == 8 && buffer [0] == 'f' && buffer [1] == 'm' && buffer [2] == 't' && buffer [3] == ' ') {
81 int sub_chunk_1_size = buffer [4];
82 sub_chunk_1_size |= buffer [5] << 8;
83 sub_chunk_1_size |= buffer [6] << 16;
84 sub_chunk_1_size |= buffer [7] << 24;
86 // Read SubChunk 1 Data
87 c = stream.Read (buffer, 0, sub_chunk_1_size);
88 if (sub_chunk_1_size == c)
91 int compression = buffer [idx++] | (buffer [idx++] << 8);
93 throw new Exception ("incorrect format (not PCM)");
94 channels = (short)(buffer [idx++] | (buffer [idx++] << 8));
95 sample_rate = buffer [idx++];
96 sample_rate |= buffer [idx++] << 8;
97 sample_rate |= buffer [idx++] << 16;
98 sample_rate |= buffer [idx++] << 24;
99 int byte_rate = buffer [idx++];
100 byte_rate |= buffer [idx++] << 8;
101 byte_rate |= buffer [idx++] << 16;
102 byte_rate |= buffer [idx++] << 24;
103 // int block_align = buffer [idx++] | (buffer [idx++] << 8);
104 int sign_bits = buffer [idx++] | (buffer [idx++] << 8);
109 format = AudioFormat.U8; break;
112 format = AudioFormat.S16_LE; break;
114 throw new Exception ("bits per sample");
118 throw new Exception ("Error: Can't Read "+sub_chunk_1_size+" bytes from stream ("+c+" bytes read");
121 throw new Exception ("incorrect format (fmt)");
124 // Read SubChunk 2 ID + Size => Could be 'fact' or 'data' !
125 c = stream.Read (buffer, 0, 8);
127 // If SubChunk 2 ID = fact
128 if (buffer [0] == 'f' && buffer [1] == 'a' && buffer [2] == 'c' && buffer [3] == 't') {
130 int sub_chunk_2_size = buffer [4];
131 sub_chunk_2_size |= buffer [5] << 8;
132 sub_chunk_2_size |= buffer [6] << 16;
133 sub_chunk_2_size |= buffer [7] << 24;
135 c = stream.Read (buffer, 0, sub_chunk_2_size);
137 // Don't care about this data !
139 // If there is a fact Chunck, read the next subChunk Id and size (should be data !)
140 c = stream.Read (buffer, 0, 8);
143 if (buffer [0] == 'd' && buffer [1] == 'a' && buffer [2] == 't' && buffer [3] == 'a') {
145 int sub_chunk_2_size = buffer [4];
146 sub_chunk_2_size |= buffer [5] << 8;
147 sub_chunk_2_size |= buffer [6] << 16;
148 sub_chunk_2_size |= buffer [7] << 24;
150 data_len = sub_chunk_2_size;
151 data_offset = stream.Position;
153 throw new Exception ("incorrect format (data/fact chunck)");
158 public override void Play (AudioDevice dev) {
159 int fragment_played = 0;
160 int total_data_played = 0;
161 int chunk_size = (int)dev.ChunkSize;
162 int count = data_len;
163 byte[] buffer = new byte [data_len];
164 byte[] chunk_to_play = new byte [chunk_size];
166 // Read only wave data, don't care about file header here !
167 stream.Position = data_offset;
168 stream.Read (buffer, 0, data_len);
170 while (!IsStopped && count >= 0){
171 // Copy one chunk from buffer
172 Buffer.BlockCopy(buffer, total_data_played, chunk_to_play, 0, chunk_size);
173 // play that chunk, !!! the size pass to alsa the number of fragment, a fragment is a sample per channel !!!
174 fragment_played = dev.PlaySample (chunk_to_play, chunk_size / (frame_divider * channels));
176 // If alsa played something, inc the total data played and dec the data to be played
177 if (fragment_played > 0) {
178 total_data_played += (fragment_played * frame_divider * channels);
179 count -= (fragment_played * frame_divider * channels);
184 public override int Channels {
185 get {return channels;}
187 public override int Rate {
188 get {return sample_rate;}
190 public override AudioFormat Format {
195 // http://en.wikipedia.org/wiki/Au_file_format
201 class AuData : AudioData {
204 ushort frame_divider;
210 public AuData (Stream data) {
212 byte[] buffer = new byte [24];
213 int c = stream.Read (buffer, 0, 24);
215 buffer [0] != '.' || buffer [1] != 's' || buffer [2] != 'n' || buffer [3] != 'd') {
216 throw new Exception ("incorrect format" + c);
218 int data_offset = buffer [7];
219 data_offset |= buffer [6] << 8;
220 data_offset |= buffer [5] << 16;
221 data_offset |= buffer [4] << 24;
222 data_len = buffer [11];
223 data_len |= buffer [10] << 8;
224 data_len |= buffer [9] << 16;
225 data_len |= buffer [8] << 24;
226 int encoding = buffer [15];
227 encoding |= buffer [14] << 8;
228 encoding |= buffer [13] << 16;
229 encoding |= buffer [12] << 24;
230 sample_rate = buffer [19];
231 sample_rate |= buffer [18] << 8;
232 sample_rate |= buffer [17] << 16;
233 sample_rate |= buffer [16] << 24;
234 int chans = buffer [23];
235 chans |= buffer [22] << 8;
236 chans |= buffer [21] << 16;
237 chans |= buffer [20] << 24;
238 channels = (short)chans;
239 if (data_offset < 24 || (chans != 1 && chans != 2)) {
240 throw new Exception ("incorrect format offset" + data_offset);
242 if (data_offset != 24) {
243 for (int l = 24; l < data_offset; ++l)
249 format = AudioFormat.MU_LAW; break;
251 throw new Exception ("incorrect format encoding" + encoding);
253 if (data_len == -1) {
254 data_len = (int)stream.Length - data_offset;
256 // Console.WriteLine ("format: {0}, rate: {1}", format, sample_rate);
259 public override void Play (AudioDevice dev) {
260 int fragment_played = 0;
261 int total_data_played = 0;
262 int chunk_size = (int)dev.ChunkSize;
263 int count = data_len;
264 byte[] buffer = new byte [data_len];
265 byte[] chunk_to_play = new byte [chunk_size];
267 // Read only Au data, don't care about file header here !
268 stream.Position = 0; //(long)data_offset;
269 stream.Read (buffer, 0, data_len);
271 while (!IsStopped && count >= 0){
272 // Copy one chunk from buffer
273 Buffer.BlockCopy(buffer, total_data_played, chunk_to_play, 0, chunk_size);
274 // play that chunk, !!! the size pass to alsa the number of fragment, a fragment is a sample per channel !!!
275 fragment_played = dev.PlaySample (chunk_to_play, chunk_size / (frame_divider * channels));
277 // If alsa played something, inc the total data played and dec the data to be played
278 if (fragment_played > 0) {
279 total_data_played += (fragment_played * frame_divider * channels);
280 count -= (fragment_played * frame_divider * channels);
285 public override int Channels {
286 get {return channels;}
288 public override int Rate {
289 get {return sample_rate;}
291 public override AudioFormat Format {