Thursday, January 27, 2011

Extracting ID3v1 tags from mp3s in C#

In 1996 Eric Kemp had the idea to add a small chunk of data to audio files; such method is now known as ID3v1. ID3 tags quickly became standard for storing metadata in MP3s. Nowadays the standard has evolved to add greater flexibility on how tags are stored (ID3v2, v2.3, and v2.4); however, for illustration purposes I will create a set of classes to read the ID3v1 tag off mp3 files.

The ID3v1 tag consists of 128 bytes of data added at the end of the file. The ID3v1 tag begins with the string TAG then it allows 30 bytes each for the title, artist, album, and comment; also, 4 bytes for the year and a byte to identify the genre and the track number.

ID3v1 tag format:
Field
Length
Description
header
3
"TAG"
title
30
30 characters of the title
artist
30
30 characters of the artist name
album
30
30 characters of the album name
year
4
A four-digit year
comment
 30
The comment.
zero-byte
1
If a track number is stored, this byte contains a binary 0.
Track
1
The number of the track on the album, or 0. Invalid, if previous byte is not a binary 0.
Genre
1
Index in a list of genres, or 255


Now that we know the expected format  we need to create a class to hold this data:

ID3Tag class:

   public class ID3Tag
    {
        public string HeaderData;
        public string TrackName;
        public string ArtistName;
        public string AlbumName;
        public string Year;
        public string Comments;
        public int ZeroByte;
        public int TrackNumber;
        public int Genre;
    }

I will add the parsing function in a separate class so if we ever want to add support for ID3v2 the project will be organized.

TagReader class:

    public class TagReader
    {


        /// <summary>
        /// Read ID3 tag
        /// </summary>
        /// <remarks>
        /// TagHeader 0-2
        /// TrackName 3-32
        /// ArtistName 33-62
        /// AlbumName 63-92
        /// Year 93-96
        /// Comment 97-126
        /// ZeroByte 125
        /// TrackNumber 126
        /// Genres 127
        /// </remarks>
        /// <param name="file">filename</param>
        /// <returns>ID3Tag object</returns>
        public ID3Tag ReadTag(string file)
        {
            ID3Tag tag = new ID3Tag();

            byte[] f = ReadID3FromFile(file);
            string data = Encoding.UTF8.GetString(f);

            if (data.Length >= 128)
            {
                tag.HeaderData = data.Substring(0,3);
                tag.TrackName = data.Substring(3, 30);
                tag.ArtistName = data.Substring(33, 30);
                tag.AlbumName = data.Substring(63, 30);
                tag.Year = data.Substring(93, 4);
                tag.Comments = data.Substring(97, 30);
                int zb = 0;
                int.TryParse(data.Substring(125, 1), out zb);
                tag.ZeroByte = zb;
                int track = 0;
                int.TryParse(data.Substring(125, 1), out track);
                tag.TrackNumber = track;
                int gen = 0;
                int.TryParse(data.Substring(127, 1), out gen);
                tag.Genre = gen;
            }

            return tag;

          
        }

        /// <summary>
        /// Read  ID3 tag from a file (last 128 bytes)
        /// </summary>
        /// <param name="mediaFile">file</param>
        /// <returns>tag segment</returns>
        private byte[] ReadID3FromFile(string mediaFile)
        {
            byte[] result = null;
            FileStream fs = null;
            BinaryReader reader = null;

            try
            {
                fs = new FileStream(mediaFile, FileMode.Open, FileAccess.Read);
                reader = new BinaryReader(fs);
                reader.BaseStream.Position = fs.Length - 128;
                result = reader.ReadBytes((int)fs.Length);
            }
            finally
            {
                if (reader != null)
                {
                    reader.Close();

                }
                if (fs != null)
                {
                    fs.Close();
                    fs.Dispose();
                }
            }
            return result;
        }
        
    }

There are only two methods in this class. ReadTag method accepts the fullpath for the media file to be read while the ReadID3FromFile does strip the ID3 tag as a byte[] to be parsed.

USAGE:
TagReader reader = new TagReader();

ID3Tag tag = reader.ReadTag(@"C:\testing\mytrack.mp3");

Console.WriteLine(tag.TrackName);
Console.WriteLine(tag.ArtistName);
Console.WriteLine(tag.AlbumName);

Console.ReadLine();




Thursday, January 20, 2011

Basic JavaScript Animation Function

Note(s):
AddEvent source code can be found here.
$ function source code can be found here.

This function is really helpful to move or change states of a DOM object in a loop.

I will start by creating the DeveloperCaster namespace (using JSON).

var DeveloperCaster = {
        Animate: function (params) {

        }
}

The function will be called Animate and it will take the following set of parameters in JSON format:

Parameters:
Animation speed, start value, end value, and action function

Example:
    var params = {
        speed:0,
        start:0,
        end:0,
        func:function (i) {}
    };





Here is the function:

    var DeveloperCaster = {
        Animate: function (params) {
            var speed = Math.round(params.speed / 1000);
            var timer = 0;
            if (params.start > params.end) {
                for (var i = params.start; i >= params.end; i--) {
                 (function (i, _f, speed, timer) {
                   setTimeout(function () { _f(i); }, (timer * speed));
                 })(i, params.func, speed, timer);
                    timer++;
                }
            } else if (params.start < params.end) {
                for (var index = params.start; index <= params.end; index++) {
                 (function (i, _f, speed, timer) {
                   setTimeout(function () { _f(i); }, (timer * speed));
                 })(index, params.func, speed, timer);
                    timer++;
                }

            }
        }
    }

The idea here is to loop from the start value to the end value while executing and passing the step parameter to the anonymous function in every step of the loop.

Usage:

JavaScript:
window.onload = function () {
            DeveloperCaster.AddEvent("b", "click", function () {
            DeveloperCaster.Animate({
                speed: 2000,
                start: 0,
                end: 300,
                func: function (i) { $('i').style.height = i + "px"; }
            });
        });

Html :
<input name="b" type="button" value="Click" />
<p>&nbsp;</p>
<div id="i" style="border:1px solid #333333">
&nbsp;
</div>


Example:
  

Whats new in Silverlight 5

Whats new in Silverlight 5

Highlights
  • Debugging DataBinding
  • Expanded Media Support
  • True 3D Support
  • P/Invoke
  • Elevated rights in the browser
  • Vector printing
  • Multiple windows (out-of-Browser only)
  • Better DataBinding
  • Custom Markup Extensions
  • UI Testing


MS planning phone-console multiplayer | Games Industry | MCV

MS planning phone-console multiplayer | Games Industry | MCV

HTC Launching Three Android Tablets - PCWorld

HTC Launching Three Android Tablets - PCWorld

Nexus S Spotted in Germany Running Android 2.4 | Android Phone Fans

Nexus S Spotted in Germany Running Android 2.4 | Android Phone Fans

Friday, January 14, 2011

C# Lambda Expression

Lambda Expressions have been part of .NET since version 3.5 (C# 3.0); so, I decided to add a quick tutorial to the blog for programmers new to C# or C# 3.0+.

Quick Definition
A lambda expression is an anonymous function that can contain expressions and statements, and can be used to create delegates or expression tree types.
From MSDN Site

In sum, a lambda expression is a way we can implement an anonymous method in less code. Besides the syntactic benefits added by Lambda expression; they also bring elements of functional programming into C# (a traditional object oriented language).

To the point

A lambda expressions must being with a parameter or set of parameters followed by the lambda symbol (=>) then the expression to be executed.

Syntax Form:
Parameter(s) => Expressions
Example 1:
X => X * 2
The example shows a function where X is the parameter following by the return expression of (X * 2).

Example 2:

Let’s declare a delegate.
public delegate int DoubleIt(int v);

Back in C# 2.0 we would have to use an anonymous method (see example below):
DoubleIt d = new DoubleIt(delegate(int x) {
     return x * 2;
 });
Console.WriteLine(d(3));

We can still use an anonymous methods; however, we can also use lambda expressions to accomplish the same thing (see example below):
DoubleIt d =  x => x * 2;
Console.WriteLine(d(3));



Example 3:
Lambda expression with multiple arguments

Let’s declare a delegate.              
public delegate int Multiply(int a, int b);
Multiply multi = (a, b) => a * b;

Console.WriteLine(multi(2, 3));

Lambda Statements

Lambda statements follow the same principle as expression; but, it encloses a full statement within brackets.

Syntax Form:
Parameter(s) => { Statement }
Example 4:
X => { Return  X * 2; }

Example 5:
Lambda statement that returns void

Let’s declare a delegate.
delegate void Greeter(string name);

...

Greeter g = new Greeter((string name) => {
                Console.WriteLine("Hello " + name);
            });
g("Walter");

Or
Greeter g = name => { string r = "Hello " + name; Console.WriteLine(r); };
g("Walter");

Output:
Hello Walter



Summary
The purpose of this post was to show you a basic implementation of lambda expressions in C# via examples without touching the functional programming subject.