/source/external/mpg123-1.25.6/ports/MSVC++/2008clr/examples/feedseekclr/Program.cs
C# | 331 lines | 219 code | 81 blank | 31 comment | 53 complexity | 4b3d79c687eb7a1a14e9a3cd598a635a MD5 | raw file
1/*
2 feedseekclr: test program for mpg123clr, showing how to use fuzzy seeking in feeder mode
3 copyright 2009 by the mpg123 project - free software under the terms of the LGPL 2.1
4 see COPYING and AUTHORS files in distribution or http://mpg123.org
5
6 based on feedseek.c example for libmpg123.
7
8 Comment (Malcolm Boczek)
9 this CLR example has been written to allow easy comparison to the original feedseek.c example
10 and uses some constructs that would not normally be used in a C# environment,
11 eg: byte[]/ASCII text, Marshal.Copy, static fields, lots of casts etc.
12*/
13
14/*
15 1.9.0.0 24-Sep-09 Function names harmonized with libmpg123 (mb)
16*/
17
18using System;
19using System.Collections.Generic;
20using System.Linq;
21using System.Text;
22
23using System.IO;
24using System.Runtime.InteropServices;
25
26using mpg123clr;
27
28namespace feedseekclr
29{
30 class Program
31 {
32 const int WAVE_FORMAT_PCM = 0x0001;
33 const int WAVE_FORMAT_IEEE_FLOAT = 0x0003;
34
35 static BinaryWriter _out;
36 static long totaloffset, dataoffset;
37 static int rate;
38 static mpg123clr.mpg.channelcount channels;
39 static mpg123clr.mpg.enc enc;
40 static short bitspersample, wavformat;
41
42 // write wav header
43 static void initwav()
44 {
45 uint tmp32 = 0;
46 ushort tmp16 = 0;
47 byte[] rifftxt = new byte[] { (byte)'R', (byte)'I', (byte)'F', (byte)'F' };
48 byte[] wavetxt = new byte[] { (byte)'W', (byte)'A', (byte)'V', (byte)'E' };
49 byte[] fmttxt = new byte[] { (byte)'f', (byte)'m', (byte)'t', (byte)' ' };
50 byte[] datatxt = new byte[] { (byte)'d', (byte)'a', (byte)'t', (byte)'a' };
51
52 _out.Write(rifftxt);
53 totaloffset = _out.BaseStream.Position;
54
55 _out.Write(tmp32); // total size
56 _out.Write(wavetxt);
57 _out.Write(fmttxt);
58
59 tmp32 = 16;
60 _out.Write(tmp32); // format length
61
62 tmp16 = (ushort)wavformat;
63 _out.Write(tmp16); // format
64
65 tmp16 = (ushort)channels;
66 _out.Write(tmp16); // channels
67
68 tmp32 = (uint)rate;
69 _out.Write(tmp32); // sample rate
70
71 tmp32 = (uint) (rate * bitspersample / 8 * (int)channels);
72 _out.Write(tmp32); // bytes / second
73
74 tmp16 = (ushort)(bitspersample / 8 * (int)channels); // float 16 or signed int 16
75 _out.Write(tmp16); // block align
76
77 tmp16 = (ushort)bitspersample;
78 _out.Write(tmp16); // bits per sample
79
80 _out.Write(datatxt);
81
82 tmp32 = 0;
83 dataoffset = _out.BaseStream.Position;
84
85 _out.Write(tmp32); // data length
86
87 }
88
89 // rewrite wav header with final length infos
90 static void closewav()
91 {
92 uint tmp32 = 0;
93 // ushort tmp16 = 0;
94
95 int total = (int)_out.BaseStream.Position;
96
97 _out.Seek((int)totaloffset, SeekOrigin.Begin);
98 tmp32 = (uint)(total - (totaloffset + 4));
99
100 _out.Write(tmp32);
101
102 _out.Seek((int)dataoffset, SeekOrigin.Begin);
103
104 tmp32 = (uint)(total - (dataoffset + 4));
105
106 _out.Write(tmp32);
107 }
108
109 // determine correct wav format and bits per sample
110 // from mpg123 enc value
111 static void initwavformat()
112 {
113 if ((enc & mpg123clr.mpg.enc.enc_float_64) != 0)
114 {
115 bitspersample = 64;
116 wavformat = WAVE_FORMAT_IEEE_FLOAT;
117 }
118 else if ((enc & mpg123clr.mpg.enc.enc_float_32) != 0)
119 {
120 bitspersample = 32;
121 wavformat = WAVE_FORMAT_IEEE_FLOAT;
122 }
123 else if ((enc & mpg123clr.mpg.enc.enc_16) != 0)
124 {
125 bitspersample = 16;
126 wavformat = WAVE_FORMAT_PCM;
127 }
128 else
129 {
130 bitspersample = 8;
131 wavformat = WAVE_FORMAT_PCM;
132 }
133 }
134
135 static void Main(string[] args)
136 {
137 const long INBUFF = 16384 * 2 * 2;
138
139 int ret;
140 mpg123clr.mpg.ErrorCode state;
141 long inoffset,inc = 0;
142 long outc = 0;
143 byte[] buf = new byte[INBUFF];
144
145 if (args.Length < 2)
146 {
147 Console.WriteLine("Please supply in and out filenames\n");
148 Console.WriteLine("Press any key to exit:");
149 while (Console.Read() == 0) ;
150
151 return;
152 }
153
154 mpg123clr.mpg.ErrorCode err;
155
156 err = mpg123.mpg123_init();
157
158 mpg123 mp = new mpg123();
159 err = mp.mpg123_new();
160
161 if (err != mpg123clr.mpg.ErrorCode.ok)
162 {
163 Console.WriteLine("Unable to create mpg123 handle: " + mpg123error.mpg123_plain_strerror(err));
164 Console.WriteLine("Press any key to exit:");
165 while (Console.Read() == 0) ;
166
167 return;
168 }
169
170 mp.mpg123_param(mpg123clr.mpg.parms.verbose, 4, 0);
171
172 err = mp.mpg123_param(mpg123clr.mpg.parms.flags,
173 (int) (mpg123clr.mpg.param_flags.fuzzy |
174 mpg123clr.mpg.param_flags.seekbuffer |
175 mpg123clr.mpg.param_flags.gapless), 0);
176
177 if (err != mpg123clr.mpg.ErrorCode.ok)
178 {
179 Console.WriteLine("Unable to set library options: " + mp.mpg123_strerror());
180 Console.WriteLine("Press any key to exit:");
181 while (Console.Read() == 0) ;
182
183 return;
184 }
185
186 // Let the seek index auto-grow and contain an entry for every frame
187 err = mp.mpg123_param(mpg123clr.mpg.parms.index_size, -1, 0);
188
189 if (err != mpg123clr.mpg.ErrorCode.ok)
190 {
191 Console.WriteLine("Unable to set index size: " + mp.mpg123_strerror());
192 Console.WriteLine("Press any key to exit:");
193 while (Console.Read() == 0) ;
194
195 return;
196 }
197
198 // Use float output formats only
199 err = mp.mpg123_format_none();
200
201 if (err != mpg123clr.mpg.ErrorCode.ok)
202 {
203 Console.WriteLine("Unable to disable all output formats: " + mp.mpg123_strerror());
204 Console.WriteLine("Press any key to exit:");
205 while (Console.Read() == 0) ;
206
207 return;
208 }
209
210 int[] rates = mp.mpg123_rates();
211 foreach (int rate in rates)
212 {
213 err = mp.mpg123_format(rate, mpg123clr.mpg.channelcount.both, mpg123clr.mpg.enc.enc_float_32);
214
215 if (err != mpg123clr.mpg.ErrorCode.ok)
216 {
217 Console.WriteLine("Unable to set float output formats: " + mp.mpg123_strerror());
218 Console.WriteLine("Press any key to exit:");
219 while (Console.Read() == 0) ;
220
221 return;
222 }
223 }
224
225 err = mp.mpg123_open_feed();
226
227 if (err != mpg123clr.mpg.ErrorCode.ok)
228 {
229 Console.WriteLine("Unable to open feed: " + mp.mpg123_strerror());
230 Console.WriteLine("Press any key to exit:");
231 while (Console.Read() == 0) ;
232
233 return;
234 }
235
236 string filename = args[0];
237 BinaryReader _in = new BinaryReader(File.Open(filename, FileMode.Open));
238
239 _out = new BinaryWriter(File.Open(args[1], FileMode.Create));
240
241 while ((ret = (int)(mp.mpg123_feedseek(95000, SeekOrigin.Begin, out inoffset))) == (int)mpg123clr.mpg.ErrorCode.need_more) // equiv to mpg123_feedseek
242 {
243 buf = _in.ReadBytes((int)INBUFF);
244
245 if (buf.Length <= 0) break;
246
247 inc += buf.Length;
248
249 state = mp.mpg123_feed(buf, (uint)buf.Length);
250
251 if (state == mpg123clr.mpg.ErrorCode.err)
252 {
253 Console.WriteLine("Feed error: " + mp.mpg123_strerror());
254 Console.WriteLine("Press any key to exit:");
255 while (Console.Read() == 0) ;
256
257 return;
258 }
259 }
260
261 _in.BaseStream.Seek(inoffset, SeekOrigin.Begin);
262
263 while (true)
264 {
265 buf = _in.ReadBytes((int)INBUFF);
266 if (buf.Length <= 0) break;
267
268 inc += buf.Length;
269
270 err = mp.mpg123_feed(buf, (uint)buf.Length);
271
272 int num;
273 uint bytes;
274 IntPtr audio;
275
276 while (err != mpg123clr.mpg.ErrorCode.err && err != mpg123clr.mpg.ErrorCode.need_more)
277 {
278 err = mp.mpg123_decode_frame(out num, out audio, out bytes);
279
280 if (err == mpg123clr.mpg.ErrorCode.new_format)
281 {
282 mp.mpg123_getformat(out rate, out channels, out enc);
283
284 initwavformat();
285 initwav();
286 }
287
288 // (Surprisingly?) even though it does a Marshal.Copy it's as efficient as the pointer example below!!!
289 if (bytes > 0)
290 {
291 byte[] outbuf = new byte[bytes];
292 Marshal.Copy(audio, outbuf, 0, (int)bytes);
293
294 _out.Write(outbuf, 0, (int)bytes);
295 }
296
297 // Alternative example of direct usage of audio data via pointers - note it needs "unsafe"
298 // and I'm fairly sure pointers should be "fixed" first
299 // if (bytes > 0)
300 // unsafe{
301 // byte* p = (byte*)audio;
302 // for (int ii = 0; ii < bytes; ii++)
303 // _out.Write(*p++);
304 // }
305
306 outc += bytes;
307 }
308
309 if (err == mpg123clr.mpg.ErrorCode.err)
310 {
311 Console.WriteLine("Error: " + mp.mpg123_strerror());
312 break;
313 }
314
315 }
316
317 Console.WriteLine("Finished");
318
319 closewav();
320
321 _out.Close();
322 _in.Close();
323
324 mp.mpg123_delete();
325 mp.Dispose();
326
327 mpg123.mpg123_exit();
328
329 }
330 }
331}