Search Unity

[OSX] Streaming / importing mp3 at runtime

Discussion in 'Scripting' started by proandrius, Sep 9, 2014.

  1. proandrius

    proandrius

    Unity Technologies

    Joined:
    Dec 4, 2012
    Posts:
    544
    Hello all,

    I would like to be able to stream / import mp3 at runtime on OSX. I was searching for the solution all over the web but I only found some solutions for Windows only (eg. NAudio).

    Maybe someone has ideas on how to achieve this? :)

    The idea is to give user to select the audio file at runtime and I would like to be able to play the file and read the samples.

    Thank You!
     
  2. MysterySoftware

    MysterySoftware

    Joined:
    Sep 18, 2014
    Posts:
    46
    I don't know about mp3-files but loading the clips in via WWW seems to work just fine.

    Edit: Sorry, I didn't really get what you what your problem was. Of course that's no solution to your mp3-streaming problem..

    Code (CSharp):
    1. void Start () {
    2.         StartCoroutine (GetTheAudio ());
    3.     }
    4.  
    5.     IEnumerator GetTheAudio() {
    6.  
    7.         WWW song = new WWW ("file:///Users/SomeUserName/Music/SomeFileName.wav");
    8.         while(!song.isDone)
    9.             yield return null;
    10.      
    11.         audio.clip = song.GetAudioClip(false, true);
    12.         audio.Play();
    13.  
    14.     }
     
    Last edited: Oct 13, 2014
  3. jister

    jister

    Joined:
    Oct 9, 2009
    Posts:
    1,700
    Has anyone found a solution to this?
    I can't seem to find any crossplatform API for this...?
     
  4. proandrius

    proandrius

    Unity Technologies

    Joined:
    Dec 4, 2012
    Posts:
    544
    Kind of. The only solution I was able to do is to convert mp3 to ogg at runtime and then stream the file. Works pretty good it just that the converting process is not that fast.

    Check out here: http://answers.unity3d.com/questions/380838/is-there-any-converter-mp3-to-ogg-.html#comment-548921

    See best answer by KoningStoma, where he talks about the plugin. But since you can't use DLL's on OSX there is this Xcode project that I was using to compile a bundle and use it instead of DLL - http://sourceforge.net/projects/mpg123net/files/latest/download
     
    jister likes this.
  5. jister

    jister

    Joined:
    Oct 9, 2009
    Posts:
    1,700
    Thanks @proandrius . I found this about making a .bundle
    but i would really appreciate it if you could do a small "steps taken by you" to use the .csproj in xcode to compile the bundle. :)
    if that's too much, could you have a look at the link and tell me if it covers everything i need to do this.
     
  6. Quingu

    Quingu

    Joined:
    Jan 30, 2013
    Posts:
    637
    When you convert from OGG to MP3 your are transcoding which makes you lose quality (lossy -> lossy).
     
  7. proandrius

    proandrius

    Unity Technologies

    Joined:
    Dec 4, 2012
    Posts:
    544
    Ah sorry, the second link was wrong, here you can download full stuff - https://sourceforge.net/projects/mpg123/files/latest/download?source=files

    And there will be Ports/Xcode folder with Xcode project in it. Just open it with Xcode and build, it will make a bundle. :)
     
  8. jister

    jister

    Joined:
    Oct 9, 2009
    Posts:
    1,700
    Awesome!! thanks again!

    @Quingu thanks for point that out. it's up to the user to choose (they can choose to load wav/mp3/ogg) :) and in my case it isn't that much about playing the audio rather than using the audio data in the neural network.
     
  9. jister

    jister

    Joined:
    Oct 9, 2009
    Posts:
    1,700
    @proandrius sorry to bother you again about this, but i get an error when building.
    I'm not that familiar in xcode.
    Screen Shot 2016-04-22 at 19.02.11.png
    there is a compat folder, but I'm not sure if it's in the right place, since a file from the libmpg123 folder is looking for it?
    Screen Shot 2016-04-22 at 19.18.16.png

    tried copying it to libmpg123 folder which made this error disappear and gave a few more instead :)
    any ideas whats going on?
     
  10. jister

    jister

    Joined:
    Oct 9, 2009
    Posts:
    1,700
    since building the xcode (7.4) project kept throwing an error. I installed mpg123 with terminal and renamed the .dylib file created to .bundle. then just rename the bundle from libmpg123.0 to libmpg123-0.
    1. Press Command+Space and type Terminal and press enter/return key.
    2. Run in Terminal app:
      ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" < /dev/null 2> /dev/null
      and press enter/return key. Wait for the command to finish.
    3. Run:
      brew install mpg123
    4. Navigate to the url shown in Terminal after installing, there you'll find the .dylib
    and finally here are the 2 scripts from KoningStoma:
    this goes in the plugins folder:
    Code (CSharp):
    1. using System;
    2. using System.Collections.Generic;
    3. using System.Text;
    4. using System.Runtime.InteropServices;
    5. using System.Security.Permissions;
    6.  
    7.  
    8.  
    9.     public class MPGImport
    10.     {          
    11.         const string Mpg123Dll = @"libmpg123.0";
    12.    
    13.     #region enums
    14.         public enum mpg123_parms
    15.         {
    16.             MPG123_VERBOSE,         /**< set verbosity value for enabling messages to stderr, >= 0 makes sense (integer) */
    17.             MPG123_FLAGS,           /**< set all flags, p.ex val = MPG123_GAPLESS|MPG123_MONO_MIX (integer) */
    18.             MPG123_ADD_FLAGS,       /**< add some flags (integer) */
    19.             MPG123_FORCE_RATE,      /**< when value > 0, force output rate to that value (integer) */
    20.             MPG123_DOWN_SAMPLE,     /**< 0=native rate, 1=half rate, 2=quarter rate (integer) */
    21.             MPG123_RVA,             /**< one of the RVA choices above (integer) */
    22.             MPG123_DOWNSPEED,       /**< play a frame N times (integer) */
    23.             MPG123_UPSPEED,         /**< play every Nth frame (integer) */
    24.             MPG123_START_FRAME,     /**< start with this frame (skip frames before that, integer) */
    25.             MPG123_DECODE_FRAMES,   /**< decode only this number of frames (integer) */
    26.             MPG123_ICY_INTERVAL,    /**< stream contains ICY metadata with this interval (integer) */
    27.             MPG123_OUTSCALE,        /**< the scale for output samples (amplitude - integer or float according to mpg123 output format, normally integer) */
    28.             MPG123_TIMEOUT,         /**< timeout for reading from a stream (not supported on win32, integer) */
    29.             MPG123_REMOVE_FLAGS,    /**< remove some flags (inverse of MPG123_ADD_FLAGS, integer) */
    30.             MPG123_RESYNC_LIMIT,    /**< Try resync on frame parsing for that many bytes or until end of stream (<0 ... integer). */
    31.             MPG123_INDEX_SIZE,      /**< Set the frame index size (if supported). Values <0 mean that the index is allowed to grow dynamically in these steps (in positive direction, of course) -- Use this when you really want a full index with every individual frame. */
    32.             MPG123_PREFRAMES        /**< Decode/ignore that many frames in advance for layer 3. This is needed to fill bit reservoir after seeking, for example (but also at least one frame in advance is needed to have all "normal" data for layer 3). Give a positive integer value, please.*/
    33.         };
    34.  
    35.         public enum mpg123_param_flags
    36.         {
    37.             MPG123_FORCE_MONO = 0x7,    /**<     0111 Force some mono mode: This is a test bitmask for seeing if any mono forcing is active. */
    38.             MPG123_MONO_LEFT = 0x1,     /**<     0001 Force playback of left channel only.  */
    39.             MPG123_MONO_RIGHT = 0x2,    /**<     0010 Force playback of right channel only. */
    40.             MPG123_MONO_MIX = 0x4,      /**<     0100 Force playback of mixed mono.         */
    41.             MPG123_FORCE_STEREO = 0x8,  /**<     1000 Force stereo output.                  */
    42.             MPG123_FORCE_8BIT = 0x10,   /**< 00010000 Force 8bit formats.                   */
    43.             MPG123_QUIET = 0x20,        /**< 00100000 Suppress any printouts (overrules verbose).                    */
    44.             MPG123_GAPLESS = 0x40,      /**< 01000000 Enable gapless decoding (default on if libmpg123 has support). */
    45.             MPG123_NO_RESYNC = 0x80,    /**< 10000000 Disable resync stream after error.                             */
    46.             MPG123_SEEKBUFFER = 0x100,  /**< 000100000000 Enable small buffer on non-seekable streams to allow some peek-ahead (for better MPEG sync). */
    47.             MPG123_FUZZY = 0x200,       /**< 001000000000 Enable fuzzy seeks (guessing byte offsets or using approximate seek points from Xing TOC) */
    48.             MPG123_FORCE_FLOAT = 0x400, /**< 010000000000 Force floating point output (32 or 64 bits depends on mpg123 internal precision). */
    49.             MPG123_PLAIN_ID3TEXT = 0x800,       /**< 100000000000 Do not translate ID3 text data to UTF-8. ID3 strings will contain the raw text data, with the first byte containing the ID3 encoding code. */
    50.             MPG123_IGNORE_STREAMLENGTH = 0x1000 /**< 1000000000000 Ignore any stream length information contained in the stream, which can be contained in a 'TLEN' frame of an ID3v2 tag or a Xing tag */
    51.         };
    52.  
    53.         /** choices for MPG123_RVA */
    54.         public enum mpg123_param_rva
    55.         {
    56.             MPG123_RVA_OFF = 0,     /**< RVA disabled (default).   */
    57.             MPG123_RVA_MIX = 1,     /**< Use mix/track/radio gain. */
    58.             MPG123_RVA_ALBUM = 2,   /**< Use album/audiophile gain */
    59.             MPG123_RVA_MAX = MPG123_RVA_ALBUM /**< The maximum RVA code, may increase in future. */
    60.         };
    61.  
    62.         public enum mpg123_feature_set
    63.         {
    64.             MPG123_FEATURE_ABI_UTF8OPEN = 0,     /**< mpg123 expects path names to be given in UTF-8 encoding instead of plain native. */
    65.             MPG123_FEATURE_OUTPUT_8BIT,          /**< 8bit output   */
    66.             MPG123_FEATURE_OUTPUT_16BIT,         /**< 16bit output  */
    67.             MPG123_FEATURE_OUTPUT_32BIT,         /**< 32bit output  */
    68.             MPG123_FEATURE_INDEX,                /**< support for building a frame index for accurate seeking */
    69.             MPG123_FEATURE_PARSE_ID3V2,          /**< id3v2 parsing */
    70.             MPG123_FEATURE_DECODE_LAYER1,        /**< mpeg layer-1 decoder enabled */
    71.             MPG123_FEATURE_DECODE_LAYER2,        /**< mpeg layer-2 decoder enabled */
    72.             MPG123_FEATURE_DECODE_LAYER3,        /**< mpeg layer-3 decoder enabled */
    73.             MPG123_FEATURE_DECODE_ACCURATE,      /**< accurate decoder rounding    */
    74.             MPG123_FEATURE_DECODE_DOWNSAMPLE,    /**< downsample (sample omit)     */
    75.             MPG123_FEATURE_DECODE_NTOM,          /**< flexible rate decoding       */
    76.             MPG123_FEATURE_PARSE_ICY,            /**< ICY support                  */
    77.             MPG123_FEATURE_TIMEOUT_READ          /**< Reader with timeout (network). */
    78.         };
    79.  
    80.         public enum mpg123_errors
    81.         {
    82.             MPG123_DONE = -12,        /**< Message: Track ended. Stop decoding. */
    83.             MPG123_NEW_FORMAT = -11,/**< Message: Output format will be different on next call. Note that some libmpg123 versions between 1.4.3 and 1.8.0 insist on you calling mpg123_getformat() after getting this message code. Newer verisons behave like advertised: You have the chance to call mpg123_getformat(), but you can also just continue decoding and get your data. */
    84.             MPG123_NEED_MORE = -10,    /**< Message: For feed reader: "Feed me more!" (call mpg123_feed() or mpg123_decode() with some new input data). */
    85.             MPG123_ERR = -1,        /**< Generic Error */
    86.             MPG123_OK = 0,             /**< Success */
    87.             MPG123_BAD_OUTFORMAT,     /**< Unable to set up output format! */
    88.             MPG123_BAD_CHANNEL,        /**< Invalid channel number specified. */
    89.             MPG123_BAD_RATE,        /**< Invalid sample rate specified.  */
    90.             MPG123_ERR_16TO8TABLE,    /**< Unable to allocate memory for 16 to 8 converter table! */
    91.             MPG123_BAD_PARAM,        /**< Bad parameter id! */
    92.             MPG123_BAD_BUFFER,        /**< Bad buffer given -- invalid pointer or too small size. */
    93.             MPG123_OUT_OF_MEM,        /**< Out of memory -- some malloc() failed. */
    94.             MPG123_NOT_INITIALIZED,    /**< You didn't initialize the library! */
    95.             MPG123_BAD_DECODER,        /**< Invalid decoder choice. */
    96.             MPG123_BAD_HANDLE,        /**< Invalid mpg123 handle. */
    97.             MPG123_NO_BUFFERS,        /**< Unable to initialize frame buffers (out of memory?). */
    98.             MPG123_BAD_RVA,            /**< Invalid RVA mode. */
    99.             MPG123_NO_GAPLESS,        /**< This build doesn't support gapless decoding. */
    100.             MPG123_NO_SPACE,        /**< Not enough buffer space. */
    101.             MPG123_BAD_TYPES,        /**< Incompatible numeric data types. */
    102.             MPG123_BAD_BAND,        /**< Bad equalizer band. */
    103.             MPG123_ERR_NULL,        /**< Null pointer given where valid storage address needed. */
    104.             MPG123_ERR_READER,        /**< Error reading the stream. */
    105.             MPG123_NO_SEEK_FROM_END,/**< Cannot seek from end (end is not known). */
    106.             MPG123_BAD_WHENCE,        /**< Invalid 'whence' for seek function.*/
    107.             MPG123_NO_TIMEOUT,        /**< Build does not support stream timeouts. */
    108.             MPG123_BAD_FILE,        /**< File access error. */
    109.             MPG123_NO_SEEK,            /**< Seek not supported by stream. */
    110.             MPG123_NO_READER,        /**< No stream opened. */
    111.             MPG123_BAD_PARS,        /**< Bad parameter handle. */
    112.             MPG123_BAD_INDEX_PAR,    /**< Bad parameters to mpg123_index() and mpg123_set_index() */
    113.             MPG123_OUT_OF_SYNC,        /**< Lost track in bytestream and did not try to resync. */
    114.             MPG123_RESYNC_FAIL,        /**< Resync failed to find valid MPEG data. */
    115.             MPG123_NO_8BIT,            /**< No 8bit encoding possible. */
    116.             MPG123_BAD_ALIGN,        /**< Stack aligmnent error */
    117.             MPG123_NULL_BUFFER,        /**< NULL input buffer with non-zero size... */
    118.             MPG123_NO_RELSEEK,        /**< Relative seek not possible (screwed up file offset) */
    119.             MPG123_NULL_POINTER,    /**< You gave a null pointer somewhere where you shouldn't have. */
    120.             MPG123_BAD_KEY,         /**< Bad key value given. */
    121.             MPG123_NO_INDEX,        /**< No frame index in this build. */
    122.             MPG123_INDEX_FAIL,        /**< Something with frame index went wrong. */
    123.             MPG123_BAD_DECODER_SETUP,    /**< Something prevents a proper decoder setup */
    124.             MPG123_MISSING_FEATURE, /**< This feature has not been built into libmpg123. */
    125.             MPG123_BAD_VALUE,       /**< A bad value has been given, somewhere. */
    126.             MPG123_LSEEK_FAILED,    /**< Low-level seek failed. */
    127.             MPG123_BAD_CUSTOM_IO,   /**< Custom I/O not prepared. */
    128.             MPG123_LFS_OVERFLOW     /**< Offset value overflow during translation of large file API calls -- your client program cannot handle that large file. */
    129.         };
    130.  
    131.         public enum mpg123_enc_enum
    132.         {
    133.             MPG123_ENC_8 = 0x00f,       /**< 0000 0000 1111 Some 8 bit  integer encoding. */
    134.             MPG123_ENC_16 = 0x040,      /**< 0000 0100 0000 Some 16 bit integer encoding. */
    135.             MPG123_ENC_32 = 0x100,      /**< 0001 0000 0000 Some 32 bit integer encoding. */
    136.             MPG123_ENC_SIGNED = 0x080,  /**< 0000 1000 0000 Some signed integer encoding. */
    137.             MPG123_ENC_FLOAT = 0xe00,   /**< 1110 0000 0000 Some float encoding. */
    138.             MPG123_ENC_SIGNED_16 = (MPG123_ENC_16 | MPG123_ENC_SIGNED | 0x10),  /**<           1101 0000 signed 16 bit */
    139.             MPG123_ENC_UNSIGNED_16 = (MPG123_ENC_16 | 0x20),                    /**<           0110 0000 unsigned 16 bit */
    140.             MPG123_ENC_UNSIGNED_8 = 0x01,                                       /**<           0000 0001 unsigned 8 bit */
    141.             MPG123_ENC_SIGNED_8 = (MPG123_ENC_SIGNED | 0x02),                   /**<           1000 0010 signed 8 bit */
    142.             MPG123_ENC_ULAW_8 = 0x04,                                           /**<           0000 0100 ulaw 8 bit */
    143.             MPG123_ENC_ALAW_8 = 0x08,                                           /**<           0000 1000 alaw 8 bit */
    144.             MPG123_ENC_SIGNED_32 = MPG123_ENC_32 | MPG123_ENC_SIGNED | 0x1000,  /**< 0001 0001 1000 0000 signed 32 bit */
    145.             MPG123_ENC_UNSIGNED_32 = MPG123_ENC_32 | 0x2000,                    /**< 0010 0001 0000 0000 unsigned 32 bit */
    146.             MPG123_ENC_FLOAT_32 = 0x200,                                        /**<      0010 0000 0000 32bit float */
    147.             MPG123_ENC_FLOAT_64 = 0x400,                                        /**<      0100 0000 0000 64bit float */
    148.             MPG123_ENC_ANY = (MPG123_ENC_SIGNED_16 | MPG123_ENC_UNSIGNED_16 | MPG123_ENC_UNSIGNED_8
    149.                              | MPG123_ENC_SIGNED_8 | MPG123_ENC_ULAW_8 | MPG123_ENC_ALAW_8
    150.                              | MPG123_ENC_SIGNED_32 | MPG123_ENC_UNSIGNED_32
    151.                              | MPG123_ENC_FLOAT_32 | MPG123_ENC_FLOAT_64)       /**< any encoding */
    152.         };
    153.  
    154.         /** They can be combined into one number (3) to indicate mono and stereo... */
    155.         public enum mpg123_channelcount
    156.         {
    157.             MPG123_MONO = 1,
    158.             MPG123_STEREO = 2
    159.         };
    160.  
    161.         public enum mpg123_channels
    162.         {
    163.             MPG123_LEFT = 0x1,    /**< The Left Channel. */
    164.             MPG123_RIGHT = 0x2,    /**< The Right Channel. */
    165.             MPG123_LR = 0x3        /**< Both left and right channel; same as MPG123_LEFT|MPG123_RIGHT */
    166.         };
    167.  
    168.         /** Enumeration of the mode types of Variable Bitrate */
    169.         public enum mpg123_vbr {
    170.             MPG123_CBR=0,    /**< Constant Bitrate Mode (default) */
    171.             MPG123_VBR,        /**< Variable Bitrate Mode */
    172.             MPG123_ABR        /**< Average Bitrate Mode */
    173.         };
    174.  
    175.         /** Enumeration of the MPEG Versions */
    176.         public enum mpg123_version {
    177.             MPG123_1_0=0,    /**< MPEG Version 1.0 */
    178.             MPG123_2_0,        /**< MPEG Version 2.0 */
    179.             MPG123_2_5        /**< MPEG Version 2.5 */
    180.         };
    181.  
    182.         /** Enumeration of the MPEG Audio mode.
    183.          *  Only the mono mode has 1 channel, the others have 2 channels. */
    184.         public enum mpg123_mode {
    185.             MPG123_M_STEREO=0,    /**< Standard Stereo. */
    186.             MPG123_M_JOINT,        /**< Joint Stereo. */
    187.             MPG123_M_DUAL,        /**< Dual Channel. */
    188.             MPG123_M_MONO        /**< Single Channel. */
    189.         };
    190.  
    191.         /** Enumeration of the MPEG Audio flag bits */
    192.         public enum mpg123_flags {
    193.             MPG123_CRC=0x1,            /**< The bitstream is error protected using 16-bit CRC. */
    194.             MPG123_COPYRIGHT=0x2,    /**< The bitstream is copyrighted. */
    195.             MPG123_PRIVATE=0x4,        /**< The private bit has been set. */
    196.             MPG123_ORIGINAL=0x8    /**< The bitstream is an original, not a copy. */
    197.         };
    198.  
    199.         public enum mpg123_state
    200.         {
    201.             MPG123_ACCURATE = 1 /**< Query if positons are currently accurate (integer value, 0 if false, 1 if true) */
    202.         };
    203.  
    204.         public enum mpg123_text_encoding
    205.         {
    206.             mpg123_text_unknown = 0,    /**< Unkown encoding... mpg123_id3_encoding can return that on invalid codes. */
    207.             mpg123_text_utf8 = 1,       /**< UTF-8 */
    208.             mpg123_text_latin1 = 2,     /**< ISO-8859-1. Note that sometimes latin1 in ID3 is abused for totally different encodings. */
    209.             mpg123_text_icy = 3,        /**< ICY metadata encoding, usually CP-1252 but we take it as UTF-8 if it qualifies as such. */
    210.             mpg123_text_cp1252 = 4,     /**< Really CP-1252 without any guessing. */
    211.             mpg123_text_utf16 = 5,      /**< Some UTF-16 encoding. The last of a set of leading BOMs (byte order mark) rules.
    212.                                          *   When there is no BOM, big endian ordering is used. Note that UCS-2 qualifies as UTF-8 when
    213.                                          *   you don't mess with the reserved code points. If you want to decode little endian data
    214.                                          *   without BOM you need to prepend 0xff 0xfe yourself. */
    215.             mpg123_text_utf16bom = 6,   /**< Just an alias for UTF-16, ID3v2 has this as distinct code. */
    216.             mpg123_text_utf16be = 7,    /**< Another alias for UTF16 from ID3v2. Note, that, because of the mess that is reality,
    217.                                          *   BOMs are used if encountered. There really is not much distinction between the UTF16 types for mpg123
    218.                                          *   One exception: Since this is seen in ID3v2 tags, leading null bytes are skipped for all other UTF16
    219.                                          *   types (we expect a BOM before real data there), not so for utf16be!*/
    220.             mpg123_text_max = 7         /**< Placeholder for the maximum encoding value. */
    221.         };
    222.  
    223.         /** The encoding byte values from ID3v2. */
    224.         public enum mpg123_id3_enc
    225.         {
    226.             mpg123_id3_latin1 = 0,      /**< Note: This sometimes can mean anything in practice... */
    227.             mpg123_id3_utf16bom = 1,    /**< UTF16, UCS-2 ... it's all the same for practical purposes. */
    228.             mpg123_id3_utf16be = 2,     /**< Big-endian UTF-16, BOM see note for mpg123_text_utf16be. */
    229.             mpg123_id3_utf8 = 3,        /**< Our lovely overly ASCII-compatible 8 byte encoding for the world. */
    230.             mpg123_id3_enc_max = 3      /**< Placeholder to check valid range of encoding byte. */
    231.         };
    232.  
    233.  
    234.  
    235.  
    236.  
    237.  
    238.     #endregion
    239.  
    240.     #region Structs
    241.  
    242.         /** Data structure for storing information about a frame of MPEG Audio */
    243.         [StructLayout(LayoutKind.Sequential)]
    244.         public struct mpg123_frameinfo
    245.         {
    246.             mpg123_version version;    /**< The MPEG version (1.0/2.0/2.5). */
    247.             int layer;                /**< The MPEG Audio Layer (MP1/MP2/MP3). */
    248.             Int32 rate;             /**< The sampling rate in Hz. */
    249.             mpg123_mode mode;        /**< The audio mode (Mono, Stereo, Joint-stero, Dual Channel). */
    250.             int mode_ext;            /**< The mode extension bit flag. */
    251.             int framesize;            /**< The size of the frame (in bytes). */
    252.             mpg123_flags flags;        /**< MPEG Audio flag bits. Just now I realize that it should be declared as int, not enum. It's a bitwise combination of the enum values. */
    253.             int emphasis;            /**< The emphasis type. */
    254.             int bitrate;            /**< Bitrate of the frame (kbps). */
    255.             int abr_rate;            /**< The target average bitrate. */
    256.             mpg123_vbr vbr;            /**< The VBR mode. */
    257.         };
    258.  
    259.         [StructLayout(LayoutKind.Sequential)]
    260.         public struct mpg123_string
    261.         {
    262.             string p; /**< pointer to the string data */
    263.             int size; /**< raw number of bytes allocated */
    264.             int fill; /**< number of used bytes (including closing zero byte) */
    265.         }
    266.  
    267.         [StructLayout(LayoutKind.Sequential)]
    268.         public struct mpg123_text
    269.         {
    270.             [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
    271.             char[] lang;                /**< Three-letter language code (not terminated). */
    272.             [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    273.             char[] id;                  /**< The ID3v2 text field id, like TALB, TPE2, ... (4 characters, no string termination). */
    274.             mpg123_string description;  /**< Empty for the generic comment... */
    275.             mpg123_string text;         /**< ... */
    276.         }
    277.  
    278.         public struct mpg123_id3v2
    279.         {
    280.             byte version;           /**< 3 or 4 for ID3v2.3 or ID3v2.4. */
    281.             IntPtr title;           /**< Title string (pointer into text_list). */
    282.             IntPtr artist;          /**< Artist string (pointer into text_list). */
    283.             IntPtr album;           /**< Album string (pointer into text_list). */
    284.             IntPtr year;            /**< The year as a string (pointer into text_list). */
    285.             IntPtr genre;           /**< Genre String (pointer into text_list). The genre string(s) may very well need postprocessing, esp. for ID3v2.3. */
    286.             IntPtr comment;         /**< Pointer to last encountered comment text with empty description. */
    287.             IntPtr comment_list;    /**< Array of comments. */
    288.             int comments;           /**< Number of comments. */
    289.             IntPtr text;            /**< Array of ID3v2 text fields (including USLT) */
    290.             int texts;              /**< Numer of text fields. */
    291.             IntPtr extra;           /**< The array of extra (TXXX) fields. */
    292.             int extras;             /**< Number of extra text (TXXX) fields. */
    293.         }
    294.  
    295.         public struct mpg123_id3v1
    296.         {
    297.             [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
    298.             public char[] tag;         /**< Always the string "TAG", the classic intro. */
    299.             [MarshalAs(UnmanagedType.ByValArray, SizeConst = 30)]
    300.             public char[] title;      /**< Title string.  */
    301.             [MarshalAs(UnmanagedType.ByValArray, SizeConst = 30)]
    302.             public char[] artist;     /**< Artist string. */
    303.             [MarshalAs(UnmanagedType.ByValArray, SizeConst = 30)]
    304.             public char[] album;      /**< Album string. */
    305.             [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    306.             public char[] year;        /**< Year string. */
    307.             [MarshalAs(UnmanagedType.ByValArray, SizeConst = 30)]
    308.             public char[] comment;    /**< Comment string. */
    309.             public byte genre;        /**< Genre index. */
    310.         }
    311.  
    312.  
    313.         #endregion
    314.  
    315.     #region Imported methods
    316.  
    317.         [DllImport(Mpg123Dll)]public static extern int mpg123_init();
    318.         [DllImport(Mpg123Dll)]public static extern void mpg123_exit();
    319.         [DllImport(Mpg123Dll, CharSet = CharSet.Ansi)]public static extern IntPtr mpg123_new(string decoder, IntPtr error);
    320.         [DllImport(Mpg123Dll)]public static extern void mpg123_delete(IntPtr mh);
    321.         [DllImport(Mpg123Dll)]public static extern int mpg123_param(IntPtr mh, mpg123_parms type, Int32 value, double fvalue);
    322.         [DllImport(Mpg123Dll)]public static extern int mpg123_getparam(IntPtr mh, mpg123_parms type, IntPtr val, IntPtr fval);
    323.         [DllImport(Mpg123Dll)]public static extern int mpg123_feature(mpg123_feature_set key);
    324.         [DllImport(Mpg123Dll, CharSet = CharSet.Ansi)]public static extern string mpg123_plain_strerror(int errcode);
    325.         [DllImport(Mpg123Dll, CharSet = CharSet.Ansi)]public static extern string mpg123_strerror(IntPtr mh);
    326.         [DllImport(Mpg123Dll)]public static extern int mpg123_errcode(IntPtr mh);      
    327.         [DllImport(Mpg123Dll, CharSet=CharSet.Ansi)]public static extern IntPtr mpg123_decoders();
    328.         [DllImport(Mpg123Dll, CharSet = CharSet.Ansi)]public static extern IntPtr mpg123_supported_decoders();
    329.         [DllImport(Mpg123Dll)]public static extern int mpg123_decoder(IntPtr mh, string decoder_name);
    330.         [DllImport(Mpg123Dll)]public static extern string mpg123_current_decoder(IntPtr mh);
    331.         [DllImport(Mpg123Dll)]public static extern void mpg123_rates(IntPtr list, IntPtr number);
    332.         [DllImport(Mpg123Dll)]public static extern void mpg123_encodings(IntPtr list, IntPtr number);
    333.         [DllImport(Mpg123Dll)]public static extern int mpg123_format_none(IntPtr mh);
    334.         [DllImport(Mpg123Dll)]public static extern int mpg123_format_all(IntPtr mh);
    335.         [DllImport(Mpg123Dll)]public static extern int mpg123_format(IntPtr mh, int rate, int channels, int encodings);
    336.         [DllImport(Mpg123Dll)]public static extern int mpg123_format_support(IntPtr mh, Int32 rate, int encoding);
    337.         [DllImport(Mpg123Dll)]public static extern int mpg123_getformat(IntPtr mh, out IntPtr rate, out IntPtr channels, out IntPtr encoding);
    338.         [DllImport(Mpg123Dll, CharSet=CharSet.Ansi)]public static extern int mpg123_open(IntPtr mh, string path);
    339.         [DllImport(Mpg123Dll)]public static extern int mpg123_open_fd(IntPtr mh, int fd);
    340.         [DllImport(Mpg123Dll)]public static extern int mpg123_open_handle(IntPtr mh, IntPtr iohandle);
    341.         [DllImport(Mpg123Dll)]public static extern int mpg123_open_feed(IntPtr mh);
    342.         [DllImport(Mpg123Dll)]public static extern int mpg123_close(IntPtr mh);
    343.         [DllImport(Mpg123Dll)]public static extern int mpg123_read(IntPtr mh, byte[] outmemory, int outmemsize, out IntPtr done);
    344.         [DllImport(Mpg123Dll)]public static extern int mpg123_feed(IntPtr mh, IntPtr input, int size);
    345.         [DllImport(Mpg123Dll)]public static extern int mpg123_decode(IntPtr mh, IntPtr inmemory, int inmemsize, IntPtr outmemory, int outmemsize, IntPtr done);
    346.         [DllImport(Mpg123Dll)]public static extern int mpg123_decode_frame(IntPtr mh, IntPtr num, IntPtr audio, IntPtr bytes);
    347.         [DllImport(Mpg123Dll)]public static extern int mpg123_framebyframe_decode(IntPtr mh, IntPtr num, IntPtr audio, IntPtr bytes);
    348.         [DllImport(Mpg123Dll)]public static extern int mpg123_framebyframe_next(IntPtr mh);
    349.         [DllImport(Mpg123Dll)]public static extern int mpg123_tell(IntPtr mh);
    350.         [DllImport(Mpg123Dll)]public static extern int mpg123_tellframe(IntPtr mh);
    351.         [DllImport(Mpg123Dll)]public static extern int mpg123_tell_stream(IntPtr mh);
    352.         [DllImport(Mpg123Dll)]public static extern int mpg123_seek(IntPtr mh, int sampleoff, int whence);
    353.         [DllImport(Mpg123Dll)]public static extern int mpg123_feedseek(IntPtr mh, int sampleoff, int whence, IntPtr input_offset);
    354.         [DllImport(Mpg123Dll)]public static extern int mpg123_seek_frame(IntPtr mh, int frameoff, int whence);
    355.         [DllImport(Mpg123Dll)]public static extern int mpg123_timeframe(IntPtr mh, double sec);
    356.         [DllImport(Mpg123Dll)]public static extern int mpg123_index(IntPtr mh, IntPtr offsets, IntPtr step, IntPtr fill);
    357.         [DllImport(Mpg123Dll)]public static extern int mpg123_set_index(IntPtr mh, IntPtr offsets, int step, int fill);
    358.         [DllImport(Mpg123Dll)]public static extern int mpg123_position( IntPtr mh, int frame_offset, int buffered_bytes, IntPtr current_frame, IntPtr frames_left, IntPtr current_seconds, IntPtr seconds_left);
    359.         [DllImport(Mpg123Dll)]public static extern int mpg123_eq(IntPtr mh, mpg123_channels channel, int band, double val);
    360.         [DllImport(Mpg123Dll)]public static extern double mpg123_geteq(IntPtr mh, mpg123_channels channel, int band);
    361.         [DllImport(Mpg123Dll)]public static extern int mpg123_reset_eq(IntPtr mh);
    362.         [DllImport(Mpg123Dll)]public static extern int mpg123_volume(IntPtr mh, double vol);
    363.         [DllImport(Mpg123Dll)]public static extern int mpg123_volume_change(IntPtr mh, double change);
    364.         [DllImport(Mpg123Dll)]public static extern int mpg123_getvolume(IntPtr mh, IntPtr _base, IntPtr really, IntPtr rva_db);
    365.         [DllImport(Mpg123Dll)]public static extern int mpg123_info(IntPtr mh, IntPtr mi);
    366.         [DllImport(Mpg123Dll)]public static extern int mpg123_safe_buffer();
    367.         [DllImport(Mpg123Dll)]public static extern int mpg123_scan(IntPtr mh);
    368.         [DllImport(Mpg123Dll)]public static extern int mpg123_length(IntPtr mh);
    369.         [DllImport(Mpg123Dll)]public static extern int mpg123_set_filesize(IntPtr mh, int size);
    370.         [DllImport(Mpg123Dll)]public static extern double mpg123_tpf(IntPtr mh);
    371.         [DllImport(Mpg123Dll)]public static extern Int32 mpg123_clip(IntPtr mh);
    372.         [DllImport(Mpg123Dll)]public static extern int mpg123_getstate(IntPtr mh, mpg123_state key, IntPtr val, IntPtr fval);
    373.         [DllImport(Mpg123Dll)]public static extern void mpg123_init_string(IntPtr sb);
    374.         [DllImport(Mpg123Dll)]public static extern void mpg123_free_string(IntPtr sb);
    375.         [DllImport(Mpg123Dll)]public static extern int  mpg123_resize_string(IntPtr sb, int news);
    376.         [DllImport(Mpg123Dll)]public static extern int  mpg123_grow_string(IntPtr sb, int news);
    377.         [DllImport(Mpg123Dll)]public static extern int  mpg123_copy_string(IntPtr from, IntPtr to);
    378.         [DllImport(Mpg123Dll)]public static extern int  mpg123_add_string(IntPtr sb, string stuff);
    379.         [DllImport(Mpg123Dll)]public static extern int  mpg123_add_substring(IntPtr sb, string stuff, int from, int count);
    380.         [DllImport(Mpg123Dll)]public static extern int  mpg123_set_string(IntPtr sb, string stuff);
    381.         [DllImport(Mpg123Dll)]public static extern int  mpg123_set_substring(IntPtr sb, string stuff, int from, int count);
    382.         [DllImport(Mpg123Dll)]public static extern mpg123_text_encoding mpg123_enc_from_id3(byte id3_enc_byte);
    383.         [DllImport(Mpg123Dll)]public static extern int mpg123_store_utf8(IntPtr sb, mpg123_text_encoding enc, string source, int source_size);
    384.         [DllImport(Mpg123Dll)]public static extern int mpg123_meta_check(IntPtr mh); /* On error (no valid handle) just 0 is returned. */
    385.         [DllImport(Mpg123Dll)]public static extern int mpg123_id3(IntPtr mh, out IntPtr v1, out IntPtr v2);
    386.         [DllImport(Mpg123Dll)]public static extern int mpg123_icy(IntPtr mh, IntPtr icy_meta); /* same for ICY meta string */
    387.         [DllImport(Mpg123Dll)]public static extern string mpg123_icy2utf8(string icy_text);
    388.         [DllImport(Mpg123Dll)]public static extern IntPtr mpg123_parnew(IntPtr mp, string decoder, IntPtr error);
    389.         [DllImport(Mpg123Dll)]public static extern IntPtr mpg123_new_pars(IntPtr error);
    390.         [DllImport(Mpg123Dll)]public static extern void mpg123_delete_pars(IntPtr mp);
    391.         [DllImport(Mpg123Dll)]public static extern int mpg123_fmt_none(IntPtr mp);
    392.         [DllImport(Mpg123Dll)]public static extern int mpg123_fmt_all(IntPtr mp);
    393.         [DllImport(Mpg123Dll)]public static extern int mpg123_fmt(IntPtr mh, Int32 rate, int channels, int encodings); /* 0 is good, -1 is error */
    394.         [DllImport(Mpg123Dll)]public static extern int mpg123_fmt_support(IntPtr mh,   Int32 rate, int encoding);
    395.         [DllImport(Mpg123Dll)]public static extern int mpg123_par(IntPtr mp, mpg123_parms type, Int32 value, double fvalue);
    396.         [DllImport(Mpg123Dll)]public static extern int mpg123_getpar(IntPtr mp, mpg123_parms type, IntPtr val, IntPtr fval);
    397.         [DllImport(Mpg123Dll)]public static extern int mpg123_replace_buffer(IntPtr mh, string data, int size);
    398.         [DllImport(Mpg123Dll)]public static extern int mpg123_outblock(IntPtr mh);
    399.  
    400.     #endregion
    401.  
    402.     }
    this goes on a gameobject:

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEditor;
    3. using System.Collections;
    4.  
    5. using System;
    6. using System.Runtime.InteropServices;
    7.  
    8.  
    9. public class MP3Import : MonoBehaviour
    10. {
    11.    
    12.     public IntPtr handle_mpg;
    13.     public IntPtr errPtr;
    14.     public IntPtr rate;
    15.     public IntPtr channels;
    16.     public IntPtr encoding;
    17.     public IntPtr id3v1;
    18.     public IntPtr id3v2;
    19.     public IntPtr done;
    20.    
    21.     public string mPath;
    22.     public int x;
    23.     public int intRate;
    24.     public int intChannels;
    25.     public int intEncoding;
    26.     public int FrameSize;
    27.     public int lengthSamples;
    28.     public AudioClip myClip;
    29.     public AudioSource audioSource;  
    30.    
    31.      #region Consts: Standard values used in almost all conversions.
    32.     private const float const_1_div_128_ = 1.0f / 128.0f;  // 8 bit multiplier
    33.     private const float const_1_div_32768_ = 1.0f / 32768.0f; // 16 bit multiplier
    34.     private const double const_1_div_2147483648_ = 1.0 / 2147483648.0; // 32 bit
    35.      #endregion
    36.    
    37.     public void StartImport()
    38.     {
    39.         if(string.IsNullOrEmpty(mPath))
    40.             mPath = EditorUtility.OpenFilePanel ("Open MP3", "", "mp3");  
    41.                
    42.         audioSource = (AudioSource)gameObject.GetComponent(typeof(AudioSource));
    43.         if(audioSource==null)audioSource=(AudioSource)gameObject.AddComponent<AudioSource>();
    44.        
    45.         MPGImport.mpg123_init ();
    46.         handle_mpg = MPGImport.mpg123_new (null, errPtr);
    47.         x = MPGImport.mpg123_open (handle_mpg, mPath);      
    48.         MPGImport.mpg123_getformat (handle_mpg, out rate, out channels, out encoding);
    49.         intRate = rate.ToInt32 ();
    50.         intChannels = channels.ToInt32 ();
    51.         intEncoding = encoding.ToInt32 ();
    52.        
    53.         MPGImport.mpg123_id3 (handle_mpg, out id3v1, out id3v2);      
    54.         MPGImport.mpg123_format_none (handle_mpg);
    55.         MPGImport.mpg123_format (handle_mpg, intRate, intChannels, 208);
    56.        
    57.         FrameSize = MPGImport.mpg123_outblock (handle_mpg);      
    58.         byte[] Buffer = new byte[FrameSize];      
    59.         lengthSamples = MPGImport.mpg123_length (handle_mpg);
    60.                
    61.         myClip = AudioClip.Create ("myClip", lengthSamples, intChannels, intRate, false, false);
    62.        
    63.         int importIndex = 0;
    64.        
    65.         while (0 == MPGImport.mpg123_read(handle_mpg, Buffer, FrameSize, out done)) {
    66.                
    67.            
    68.             float[] fArray;
    69.             fArray = ByteToFloat (Buffer);
    70.                                
    71.             myClip.SetData (fArray, (importIndex*fArray.Length)/2);
    72.            
    73.             importIndex++;                
    74.         }          
    75.        
    76.         MPGImport.mpg123_close (handle_mpg);
    77.                        
    78.         audioSource.clip = myClip;
    79.         audioSource.loop = true;
    80.         audioSource.Play ();
    81.     }
    82.        
    83. //    void Start ()
    84. //    {
    85. //        StartImport();
    86. //    }
    87.  
    88.     public float[] IntToFloat (Int16[] from)
    89.     {
    90.         float[] to = new float[from.Length];
    91.            
    92.         for (int i = 0; i < from.Length; i++)
    93.             to [i] = (float)(from [i] * const_1_div_32768_);
    94.  
    95.         return to;
    96.     }
    97.  
    98.     public Int16[] ByteToInt16 (byte[] buffer)
    99.     {
    100.         Int16[] result = new Int16[1];
    101.         int size = buffer.Length;
    102.         if ((size % 2) != 0) {
    103.             /* Error here */
    104.             Console.WriteLine ("error");
    105.             return result;
    106.         } else {
    107.             result = new Int16[size / 2];
    108.             IntPtr ptr_src = Marshal.AllocHGlobal (size);
    109.             Marshal.Copy (buffer, 0, ptr_src, size);
    110.             Marshal.Copy (ptr_src, result, 0, result.Length);
    111.             Marshal.FreeHGlobal (ptr_src);
    112.             return result;
    113.         }
    114.     }
    115.    
    116.     public float[] ByteToFloat (byte[] bArray)
    117.     {
    118.         Int16[] iArray;      
    119.            
    120.         iArray = ByteToInt16 (bArray);
    121.        
    122.         return IntToFloat (iArray);
    123.     }
    124.    
    125.    
    126. }
     
unityunity