Blame ports/MSVC++/2008clr/examples/feedseekclr/Program.cs

Packit c32a2d
/*
Packit c32a2d
	feedseekclr: test program for mpg123clr, showing how to use fuzzy seeking in feeder mode
Packit c32a2d
	copyright 2009 by the mpg123 project - free software under the terms of the LGPL 2.1
Packit c32a2d
	see COPYING and AUTHORS files in distribution or http://mpg123.org	
Packit c32a2d

Packit c32a2d
    based on feedseek.c example for libmpg123.
Packit c32a2d
 
Packit c32a2d
    Comment (Malcolm Boczek)
Packit c32a2d
    this CLR example has been written to allow easy comparison to the original feedseek.c example
Packit c32a2d
    and uses some constructs that would not normally be used in a C# environment,
Packit c32a2d
        eg: byte[]/ASCII text, Marshal.Copy, static fields, lots of casts etc.
Packit c32a2d
*/
Packit c32a2d

Packit c32a2d
/*
Packit c32a2d
	1.9.0.0 24-Sep-09	Function names harmonized with libmpg123 (mb)
Packit c32a2d
*/
Packit c32a2d

Packit c32a2d
using System;
Packit c32a2d
using System.Collections.Generic;
Packit c32a2d
using System.Linq;
Packit c32a2d
using System.Text;
Packit c32a2d

Packit c32a2d
using System.IO;
Packit c32a2d
using System.Runtime.InteropServices;
Packit c32a2d

Packit c32a2d
using mpg123clr;
Packit c32a2d

Packit c32a2d
namespace feedseekclr
Packit c32a2d
{
Packit c32a2d
    class Program
Packit c32a2d
    {
Packit c32a2d
        const int WAVE_FORMAT_PCM = 0x0001;
Packit c32a2d
        const int WAVE_FORMAT_IEEE_FLOAT = 0x0003;
Packit c32a2d

Packit c32a2d
        static BinaryWriter _out;
Packit c32a2d
        static long totaloffset, dataoffset;
Packit c32a2d
        static int rate;
Packit c32a2d
        static mpg123clr.mpg.channelcount channels;
Packit c32a2d
        static mpg123clr.mpg.enc enc;
Packit c32a2d
        static short bitspersample, wavformat;
Packit c32a2d

Packit c32a2d
        // write wav header
Packit c32a2d
        static void initwav()
Packit c32a2d
        {
Packit c32a2d
            uint tmp32 = 0;
Packit c32a2d
            ushort tmp16 = 0;
Packit c32a2d
            byte[] rifftxt = new byte[] { (byte)'R', (byte)'I', (byte)'F', (byte)'F' };
Packit c32a2d
            byte[] wavetxt = new byte[] { (byte)'W', (byte)'A', (byte)'V', (byte)'E' };
Packit c32a2d
            byte[] fmttxt  = new byte[] { (byte)'f', (byte)'m', (byte)'t', (byte)' ' };
Packit c32a2d
            byte[] datatxt = new byte[] { (byte)'d', (byte)'a', (byte)'t', (byte)'a' };
Packit c32a2d

Packit c32a2d
            _out.Write(rifftxt);
Packit c32a2d
            totaloffset = _out.BaseStream.Position;
Packit c32a2d

Packit c32a2d
            _out.Write(tmp32); // total size
Packit c32a2d
            _out.Write(wavetxt);
Packit c32a2d
            _out.Write(fmttxt);
Packit c32a2d

Packit c32a2d
            tmp32 = 16;
Packit c32a2d
            _out.Write(tmp32); // format length
Packit c32a2d

Packit c32a2d
            tmp16 = (ushort)wavformat;
Packit c32a2d
            _out.Write(tmp16); // format
Packit c32a2d

Packit c32a2d
            tmp16 = (ushort)channels;
Packit c32a2d
            _out.Write(tmp16); // channels
Packit c32a2d

Packit c32a2d
            tmp32 = (uint)rate;
Packit c32a2d
            _out.Write(tmp32); // sample rate
Packit c32a2d

Packit c32a2d
            tmp32 = (uint) (rate * bitspersample / 8 * (int)channels);
Packit c32a2d
            _out.Write(tmp32); // bytes / second
Packit c32a2d

Packit c32a2d
            tmp16 = (ushort)(bitspersample / 8 * (int)channels); // float 16 or signed int 16
Packit c32a2d
            _out.Write(tmp16); // block align
Packit c32a2d

Packit c32a2d
            tmp16 = (ushort)bitspersample;
Packit c32a2d
            _out.Write(tmp16); // bits per sample
Packit c32a2d

Packit c32a2d
            _out.Write(datatxt);
Packit c32a2d

Packit c32a2d
            tmp32 = 0;
Packit c32a2d
            dataoffset = _out.BaseStream.Position;
Packit c32a2d

Packit c32a2d
            _out.Write(tmp32); // data length
Packit c32a2d

Packit c32a2d
        }
Packit c32a2d

Packit c32a2d
        // rewrite wav header with final length infos
Packit c32a2d
        static void closewav()
Packit c32a2d
        {
Packit c32a2d
            uint tmp32 = 0;
Packit c32a2d
            // ushort tmp16 = 0;
Packit c32a2d

Packit c32a2d
            int total = (int)_out.BaseStream.Position;
Packit c32a2d

Packit c32a2d
            _out.Seek((int)totaloffset, SeekOrigin.Begin);
Packit c32a2d
            tmp32 = (uint)(total - (totaloffset + 4));
Packit c32a2d

Packit c32a2d
            _out.Write(tmp32);
Packit c32a2d

Packit c32a2d
            _out.Seek((int)dataoffset, SeekOrigin.Begin);
Packit c32a2d

Packit c32a2d
            tmp32 = (uint)(total - (dataoffset + 4));
Packit c32a2d

Packit c32a2d
            _out.Write(tmp32);
Packit c32a2d
        }
Packit c32a2d

Packit c32a2d
        // determine correct wav format and bits per sample
Packit c32a2d
        // from mpg123 enc value
Packit c32a2d
        static void initwavformat()
Packit c32a2d
        {
Packit c32a2d
            if ((enc & mpg123clr.mpg.enc.enc_float_64) != 0)
Packit c32a2d
            {
Packit c32a2d
                bitspersample = 64;
Packit c32a2d
                wavformat = WAVE_FORMAT_IEEE_FLOAT;
Packit c32a2d
            }
Packit c32a2d
            else if ((enc & mpg123clr.mpg.enc.enc_float_32) != 0)
Packit c32a2d
            {
Packit c32a2d
                bitspersample = 32;
Packit c32a2d
                wavformat = WAVE_FORMAT_IEEE_FLOAT;
Packit c32a2d
            }
Packit c32a2d
            else if ((enc & mpg123clr.mpg.enc.enc_16) != 0)
Packit c32a2d
            {
Packit c32a2d
                bitspersample = 16;
Packit c32a2d
                wavformat = WAVE_FORMAT_PCM;
Packit c32a2d
            }
Packit c32a2d
            else
Packit c32a2d
            {
Packit c32a2d
                bitspersample = 8;
Packit c32a2d
                wavformat = WAVE_FORMAT_PCM;
Packit c32a2d
            }
Packit c32a2d
        }
Packit c32a2d

Packit c32a2d
        static void Main(string[] args)
Packit c32a2d
        {
Packit c32a2d
            const long INBUFF = 16384 * 2 * 2;
Packit c32a2d

Packit c32a2d
            int ret;
Packit c32a2d
            mpg123clr.mpg.ErrorCode state;
Packit c32a2d
            long inoffset,inc = 0;
Packit c32a2d
            long outc = 0;
Packit c32a2d
            byte[] buf = new byte[INBUFF];
Packit c32a2d

Packit c32a2d
            if (args.Length < 2)
Packit c32a2d
            {
Packit c32a2d
                Console.WriteLine("Please supply in and out filenames\n");
Packit c32a2d
                Console.WriteLine("Press any key to exit:");
Packit c32a2d
                while (Console.Read() == 0) ;
Packit c32a2d

Packit c32a2d
                return;
Packit c32a2d
            }
Packit c32a2d

Packit c32a2d
            mpg123clr.mpg.ErrorCode err;
Packit c32a2d

Packit c32a2d
            err = mpg123.mpg123_init();
Packit c32a2d

Packit c32a2d
            mpg123 mp = new mpg123();
Packit c32a2d
            err = mp.mpg123_new();
Packit c32a2d

Packit c32a2d
            if (err != mpg123clr.mpg.ErrorCode.ok)
Packit c32a2d
            {
Packit c32a2d
                Console.WriteLine("Unable to create mpg123 handle: " + mpg123error.mpg123_plain_strerror(err));
Packit c32a2d
                Console.WriteLine("Press any key to exit:");
Packit c32a2d
                while (Console.Read() == 0) ;
Packit c32a2d

Packit c32a2d
                return;
Packit c32a2d
            }
Packit c32a2d

Packit c32a2d
            mp.mpg123_param(mpg123clr.mpg.parms.verbose, 4, 0);
Packit c32a2d

Packit c32a2d
            err = mp.mpg123_param(mpg123clr.mpg.parms.flags, 
Packit c32a2d
                (int) (mpg123clr.mpg.param_flags.fuzzy | 
Packit c32a2d
                mpg123clr.mpg.param_flags.seekbuffer | 
Packit c32a2d
                mpg123clr.mpg.param_flags.gapless), 0);
Packit c32a2d

Packit c32a2d
            if (err != mpg123clr.mpg.ErrorCode.ok)
Packit c32a2d
            {
Packit c32a2d
                Console.WriteLine("Unable to set library options: " + mp.mpg123_strerror());
Packit c32a2d
                Console.WriteLine("Press any key to exit:");
Packit c32a2d
                while (Console.Read() == 0) ;
Packit c32a2d

Packit c32a2d
                return;
Packit c32a2d
            }
Packit c32a2d

Packit c32a2d
            // Let the seek index auto-grow and contain an entry for every frame
Packit c32a2d
            err = mp.mpg123_param(mpg123clr.mpg.parms.index_size, -1, 0);
Packit c32a2d

Packit c32a2d
            if (err != mpg123clr.mpg.ErrorCode.ok)
Packit c32a2d
            {
Packit c32a2d
                Console.WriteLine("Unable to set index size: " + mp.mpg123_strerror());
Packit c32a2d
                Console.WriteLine("Press any key to exit:");
Packit c32a2d
                while (Console.Read() == 0) ;
Packit c32a2d

Packit c32a2d
                return;
Packit c32a2d
            }
Packit c32a2d

Packit c32a2d
            // Use float output formats only
Packit c32a2d
            err = mp.mpg123_format_none();
Packit c32a2d

Packit c32a2d
            if (err != mpg123clr.mpg.ErrorCode.ok)
Packit c32a2d
            {
Packit c32a2d
                Console.WriteLine("Unable to disable all output formats: " + mp.mpg123_strerror());
Packit c32a2d
                Console.WriteLine("Press any key to exit:");
Packit c32a2d
                while (Console.Read() == 0) ;
Packit c32a2d

Packit c32a2d
                return;
Packit c32a2d
            }
Packit c32a2d

Packit c32a2d
            int[] rates = mp.mpg123_rates();
Packit c32a2d
            foreach (int rate in rates)
Packit c32a2d
            {
Packit c32a2d
                err = mp.mpg123_format(rate, mpg123clr.mpg.channelcount.both, mpg123clr.mpg.enc.enc_float_32);
Packit c32a2d

Packit c32a2d
                if (err != mpg123clr.mpg.ErrorCode.ok)
Packit c32a2d
                {
Packit c32a2d
                    Console.WriteLine("Unable to set float output formats: " + mp.mpg123_strerror());
Packit c32a2d
                    Console.WriteLine("Press any key to exit:");
Packit c32a2d
                    while (Console.Read() == 0) ;
Packit c32a2d

Packit c32a2d
                    return;
Packit c32a2d
                }
Packit c32a2d
            }
Packit c32a2d

Packit c32a2d
            err = mp.mpg123_open_feed();
Packit c32a2d

Packit c32a2d
            if (err != mpg123clr.mpg.ErrorCode.ok)
Packit c32a2d
            {
Packit c32a2d
                Console.WriteLine("Unable to open feed: " + mp.mpg123_strerror());
Packit c32a2d
                Console.WriteLine("Press any key to exit:");
Packit c32a2d
                while (Console.Read() == 0) ;
Packit c32a2d

Packit c32a2d
                return;
Packit c32a2d
            }
Packit c32a2d

Packit c32a2d
            string filename = args[0];
Packit c32a2d
            BinaryReader _in = new BinaryReader(File.Open(filename, FileMode.Open));
Packit c32a2d

Packit c32a2d
            _out = new BinaryWriter(File.Open(args[1], FileMode.Create));
Packit c32a2d

Packit c32a2d
            while ((ret = (int)(mp.mpg123_feedseek(95000, SeekOrigin.Begin, out inoffset))) == (int)mpg123clr.mpg.ErrorCode.need_more) // equiv to mpg123_feedseek
Packit c32a2d
            {
Packit c32a2d
                buf = _in.ReadBytes((int)INBUFF);
Packit c32a2d

Packit c32a2d
                if (buf.Length <= 0) break;
Packit c32a2d

Packit c32a2d
                inc += buf.Length;
Packit c32a2d

Packit c32a2d
                state = mp.mpg123_feed(buf, (uint)buf.Length); 
Packit c32a2d

Packit c32a2d
                if (state == mpg123clr.mpg.ErrorCode.err)
Packit c32a2d
                {
Packit c32a2d
                    Console.WriteLine("Feed error: " + mp.mpg123_strerror());
Packit c32a2d
                    Console.WriteLine("Press any key to exit:");
Packit c32a2d
                    while (Console.Read() == 0) ;
Packit c32a2d

Packit c32a2d
                    return;
Packit c32a2d
                }
Packit c32a2d
            }
Packit c32a2d

Packit c32a2d
            _in.BaseStream.Seek(inoffset, SeekOrigin.Begin);
Packit c32a2d

Packit c32a2d
            while (true)
Packit c32a2d
            {
Packit c32a2d
                buf = _in.ReadBytes((int)INBUFF);
Packit c32a2d
                if (buf.Length <= 0) break;
Packit c32a2d

Packit c32a2d
                inc += buf.Length;
Packit c32a2d

Packit c32a2d
                err = mp.mpg123_feed(buf, (uint)buf.Length); 
Packit c32a2d

Packit c32a2d
                int num;
Packit c32a2d
                uint bytes;
Packit c32a2d
                IntPtr audio;
Packit c32a2d

Packit c32a2d
                while (err != mpg123clr.mpg.ErrorCode.err && err != mpg123clr.mpg.ErrorCode.need_more)
Packit c32a2d
                {
Packit c32a2d
                    err = mp.mpg123_decode_frame(out num, out audio, out bytes); 
Packit c32a2d

Packit c32a2d
                    if (err == mpg123clr.mpg.ErrorCode.new_format)
Packit c32a2d
                    {
Packit c32a2d
                        mp.mpg123_getformat(out rate, out channels, out enc); 
Packit c32a2d

Packit c32a2d
                        initwavformat();
Packit c32a2d
                        initwav();
Packit c32a2d
                    }
Packit c32a2d

Packit c32a2d
                    // (Surprisingly?) even though it does a Marshal.Copy it's as efficient as the pointer example below!!!
Packit c32a2d
                    if (bytes > 0)
Packit c32a2d
                    {
Packit c32a2d
                        byte[] outbuf = new byte[bytes];
Packit c32a2d
                        Marshal.Copy(audio, outbuf, 0, (int)bytes);
Packit c32a2d

Packit c32a2d
                        _out.Write(outbuf, 0, (int)bytes);
Packit c32a2d
                    }
Packit c32a2d

Packit c32a2d
                    // Alternative example of direct usage of audio data via pointers - note it needs "unsafe"
Packit c32a2d
                    //  and I'm fairly sure pointers should be "fixed" first
Packit c32a2d
                    // if (bytes > 0)
Packit c32a2d
                    // unsafe{
Packit c32a2d
                    //        byte* p = (byte*)audio;
Packit c32a2d
                    //        for (int ii = 0; ii < bytes; ii++)
Packit c32a2d
                    //            _out.Write(*p++);
Packit c32a2d
                    // }
Packit c32a2d

Packit c32a2d
                    outc += bytes;
Packit c32a2d
                }
Packit c32a2d

Packit c32a2d
                if (err == mpg123clr.mpg.ErrorCode.err)
Packit c32a2d
                {
Packit c32a2d
                    Console.WriteLine("Error: " + mp.mpg123_strerror());
Packit c32a2d
                    break;
Packit c32a2d
                }
Packit c32a2d

Packit c32a2d
            }
Packit c32a2d

Packit c32a2d
            Console.WriteLine("Finished");
Packit c32a2d

Packit c32a2d
            closewav();
Packit c32a2d

Packit c32a2d
            _out.Close();
Packit c32a2d
            _in.Close();
Packit c32a2d

Packit c32a2d
            mp.mpg123_delete();
Packit c32a2d
            mp.Dispose();
Packit c32a2d

Packit c32a2d
            mpg123.mpg123_exit();
Packit c32a2d

Packit c32a2d
        }
Packit c32a2d
    }
Packit c32a2d
}