PageRenderTime 42ms CodeModel.GetById 28ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/source/external/mpg123-1.25.6/ports/MSVC++/2008clr/examples/feedseekclr/Program.cs

https://bitbucket.org/liflg/library-sdl2-mixer
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}