/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
- /*
- feedseekclr: test program for mpg123clr, showing how to use fuzzy seeking in feeder mode
- copyright 2009 by the mpg123 project - free software under the terms of the LGPL 2.1
- see COPYING and AUTHORS files in distribution or http://mpg123.org
-
- based on feedseek.c example for libmpg123.
-
- Comment (Malcolm Boczek)
- this CLR example has been written to allow easy comparison to the original feedseek.c example
- and uses some constructs that would not normally be used in a C# environment,
- eg: byte[]/ASCII text, Marshal.Copy, static fields, lots of casts etc.
- */
-
- /*
- 1.9.0.0 24-Sep-09 Function names harmonized with libmpg123 (mb)
- */
-
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
-
- using System.IO;
- using System.Runtime.InteropServices;
-
- using mpg123clr;
-
- namespace feedseekclr
- {
- class Program
- {
- const int WAVE_FORMAT_PCM = 0x0001;
- const int WAVE_FORMAT_IEEE_FLOAT = 0x0003;
-
- static BinaryWriter _out;
- static long totaloffset, dataoffset;
- static int rate;
- static mpg123clr.mpg.channelcount channels;
- static mpg123clr.mpg.enc enc;
- static short bitspersample, wavformat;
-
- // write wav header
- static void initwav()
- {
- uint tmp32 = 0;
- ushort tmp16 = 0;
- byte[] rifftxt = new byte[] { (byte)'R', (byte)'I', (byte)'F', (byte)'F' };
- byte[] wavetxt = new byte[] { (byte)'W', (byte)'A', (byte)'V', (byte)'E' };
- byte[] fmttxt = new byte[] { (byte)'f', (byte)'m', (byte)'t', (byte)' ' };
- byte[] datatxt = new byte[] { (byte)'d', (byte)'a', (byte)'t', (byte)'a' };
-
- _out.Write(rifftxt);
- totaloffset = _out.BaseStream.Position;
-
- _out.Write(tmp32); // total size
- _out.Write(wavetxt);
- _out.Write(fmttxt);
-
- tmp32 = 16;
- _out.Write(tmp32); // format length
-
- tmp16 = (ushort)wavformat;
- _out.Write(tmp16); // format
-
- tmp16 = (ushort)channels;
- _out.Write(tmp16); // channels
-
- tmp32 = (uint)rate;
- _out.Write(tmp32); // sample rate
-
- tmp32 = (uint) (rate * bitspersample / 8 * (int)channels);
- _out.Write(tmp32); // bytes / second
-
- tmp16 = (ushort)(bitspersample / 8 * (int)channels); // float 16 or signed int 16
- _out.Write(tmp16); // block align
-
- tmp16 = (ushort)bitspersample;
- _out.Write(tmp16); // bits per sample
-
- _out.Write(datatxt);
-
- tmp32 = 0;
- dataoffset = _out.BaseStream.Position;
-
- _out.Write(tmp32); // data length
-
- }
-
- // rewrite wav header with final length infos
- static void closewav()
- {
- uint tmp32 = 0;
- // ushort tmp16 = 0;
-
- int total = (int)_out.BaseStream.Position;
-
- _out.Seek((int)totaloffset, SeekOrigin.Begin);
- tmp32 = (uint)(total - (totaloffset + 4));
-
- _out.Write(tmp32);
-
- _out.Seek((int)dataoffset, SeekOrigin.Begin);
-
- tmp32 = (uint)(total - (dataoffset + 4));
-
- _out.Write(tmp32);
- }
-
- // determine correct wav format and bits per sample
- // from mpg123 enc value
- static void initwavformat()
- {
- if ((enc & mpg123clr.mpg.enc.enc_float_64) != 0)
- {
- bitspersample = 64;
- wavformat = WAVE_FORMAT_IEEE_FLOAT;
- }
- else if ((enc & mpg123clr.mpg.enc.enc_float_32) != 0)
- {
- bitspersample = 32;
- wavformat = WAVE_FORMAT_IEEE_FLOAT;
- }
- else if ((enc & mpg123clr.mpg.enc.enc_16) != 0)
- {
- bitspersample = 16;
- wavformat = WAVE_FORMAT_PCM;
- }
- else
- {
- bitspersample = 8;
- wavformat = WAVE_FORMAT_PCM;
- }
- }
-
- static void Main(string[] args)
- {
- const long INBUFF = 16384 * 2 * 2;
-
- int ret;
- mpg123clr.mpg.ErrorCode state;
- long inoffset,inc = 0;
- long outc = 0;
- byte[] buf = new byte[INBUFF];
-
- if (args.Length < 2)
- {
- Console.WriteLine("Please supply in and out filenames\n");
- Console.WriteLine("Press any key to exit:");
- while (Console.Read() == 0) ;
-
- return;
- }
-
- mpg123clr.mpg.ErrorCode err;
-
- err = mpg123.mpg123_init();
-
- mpg123 mp = new mpg123();
- err = mp.mpg123_new();
-
- if (err != mpg123clr.mpg.ErrorCode.ok)
- {
- Console.WriteLine("Unable to create mpg123 handle: " + mpg123error.mpg123_plain_strerror(err));
- Console.WriteLine("Press any key to exit:");
- while (Console.Read() == 0) ;
-
- return;
- }
-
- mp.mpg123_param(mpg123clr.mpg.parms.verbose, 4, 0);
-
- err = mp.mpg123_param(mpg123clr.mpg.parms.flags,
- (int) (mpg123clr.mpg.param_flags.fuzzy |
- mpg123clr.mpg.param_flags.seekbuffer |
- mpg123clr.mpg.param_flags.gapless), 0);
-
- if (err != mpg123clr.mpg.ErrorCode.ok)
- {
- Console.WriteLine("Unable to set library options: " + mp.mpg123_strerror());
- Console.WriteLine("Press any key to exit:");
- while (Console.Read() == 0) ;
-
- return;
- }
-
- // Let the seek index auto-grow and contain an entry for every frame
- err = mp.mpg123_param(mpg123clr.mpg.parms.index_size, -1, 0);
-
- if (err != mpg123clr.mpg.ErrorCode.ok)
- {
- Console.WriteLine("Unable to set index size: " + mp.mpg123_strerror());
- Console.WriteLine("Press any key to exit:");
- while (Console.Read() == 0) ;
-
- return;
- }
-
- // Use float output formats only
- err = mp.mpg123_format_none();
-
- if (err != mpg123clr.mpg.ErrorCode.ok)
- {
- Console.WriteLine("Unable to disable all output formats: " + mp.mpg123_strerror());
- Console.WriteLine("Press any key to exit:");
- while (Console.Read() == 0) ;
-
- return;
- }
-
- int[] rates = mp.mpg123_rates();
- foreach (int rate in rates)
- {
- err = mp.mpg123_format(rate, mpg123clr.mpg.channelcount.both, mpg123clr.mpg.enc.enc_float_32);
-
- if (err != mpg123clr.mpg.ErrorCode.ok)
- {
- Console.WriteLine("Unable to set float output formats: " + mp.mpg123_strerror());
- Console.WriteLine("Press any key to exit:");
- while (Console.Read() == 0) ;
-
- return;
- }
- }
-
- err = mp.mpg123_open_feed();
-
- if (err != mpg123clr.mpg.ErrorCode.ok)
- {
- Console.WriteLine("Unable to open feed: " + mp.mpg123_strerror());
- Console.WriteLine("Press any key to exit:");
- while (Console.Read() == 0) ;
-
- return;
- }
-
- string filename = args[0];
- BinaryReader _in = new BinaryReader(File.Open(filename, FileMode.Open));
-
- _out = new BinaryWriter(File.Open(args[1], FileMode.Create));
-
- while ((ret = (int)(mp.mpg123_feedseek(95000, SeekOrigin.Begin, out inoffset))) == (int)mpg123clr.mpg.ErrorCode.need_more) // equiv to mpg123_feedseek
- {
- buf = _in.ReadBytes((int)INBUFF);
-
- if (buf.Length <= 0) break;
-
- inc += buf.Length;
-
- state = mp.mpg123_feed(buf, (uint)buf.Length);
-
- if (state == mpg123clr.mpg.ErrorCode.err)
- {
- Console.WriteLine("Feed error: " + mp.mpg123_strerror());
- Console.WriteLine("Press any key to exit:");
- while (Console.Read() == 0) ;
-
- return;
- }
- }
-
- _in.BaseStream.Seek(inoffset, SeekOrigin.Begin);
-
- while (true)
- {
- buf = _in.ReadBytes((int)INBUFF);
- if (buf.Length <= 0) break;
-
- inc += buf.Length;
-
- err = mp.mpg123_feed(buf, (uint)buf.Length);
-
- int num;
- uint bytes;
- IntPtr audio;
-
- while (err != mpg123clr.mpg.ErrorCode.err && err != mpg123clr.mpg.ErrorCode.need_more)
- {
- err = mp.mpg123_decode_frame(out num, out audio, out bytes);
-
- if (err == mpg123clr.mpg.ErrorCode.new_format)
- {
- mp.mpg123_getformat(out rate, out channels, out enc);
-
- initwavformat();
- initwav();
- }
-
- // (Surprisingly?) even though it does a Marshal.Copy it's as efficient as the pointer example below!!!
- if (bytes > 0)
- {
- byte[] outbuf = new byte[bytes];
- Marshal.Copy(audio, outbuf, 0, (int)bytes);
-
- _out.Write(outbuf, 0, (int)bytes);
- }
-
- // Alternative example of direct usage of audio data via pointers - note it needs "unsafe"
- // and I'm fairly sure pointers should be "fixed" first
- // if (bytes > 0)
- // unsafe{
- // byte* p = (byte*)audio;
- // for (int ii = 0; ii < bytes; ii++)
- // _out.Write(*p++);
- // }
-
- outc += bytes;
- }
-
- if (err == mpg123clr.mpg.ErrorCode.err)
- {
- Console.WriteLine("Error: " + mp.mpg123_strerror());
- break;
- }
-
- }
-
- Console.WriteLine("Finished");
-
- closewav();
-
- _out.Close();
- _in.Close();
-
- mp.mpg123_delete();
- mp.Dispose();
-
- mpg123.mpg123_exit();
-
- }
- }
- }