Home > utils > mp3read.m

mp3read

PURPOSE ^

[Y,FS,NBITS,OPTS] = mp3read(FILE,N,MONO,DOWNSAMP) Read MP3 audio file

SYNOPSIS ^

function [Y,FS,NBITS,OPTS] = mp3read(FILE,N,MONO,DOWNSAMP)

DESCRIPTION ^

 [Y,FS,NBITS,OPTS] = mp3read(FILE,N,MONO,DOWNSAMP)   Read MP3 audio file
       FILE is an MP3 audio file name.  Optional scalar N limits the number 
       of frames to read, or, if a two-element vector, specifies 
       the first and last frames to read.
       Optional flag MONO forces result to be mono if nonzero;
       Optional factor DOWNSAMP performs downsampling by 2 or 4.
       Y returns the audio data, one channel per column; FS is the 
       sampling rate.  NBITS is the bit depth (always 16). 
       OPTS.fmt is a format info string.
 2003-07-20 dpwe@ee.columbia.edu  This version calls mpg123.
 2004-08-31 Fixed to read whole files correctly
 2004-09-08 Uses mp3info to get info about mp3 files too
 2004-09-18 Reports all mp3info fields in OPTS.fmt; handles MPG2LSF sizes
            + added MONO, DOWNSAMP flags, changed default behavior.
 2005-04-11 added -r m for report of median VBR in mp3info (thx Merrie Morris)
 2006-01-09 Petr Janata - fixed argument list to mpg123 (see below).  Allowed
            passing N = [];
 2011-07-01 PJ - mpg123 would sometimes return insufficient data when only
            a partial read was requested, so a bit extra is being requested now
 2014-08-20 PJ - added dynamic mpg123, mp3info location based on
                 architecture
 $Header: /homes/dpwe/matlab/columbiafns/RCS/mp3read.m,v 1.7 2005/04/11 20:55:16 dpwe Exp $

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function [Y,FS,NBITS,OPTS] = mp3read(FILE,N,MONO,DOWNSAMP)
0002 % [Y,FS,NBITS,OPTS] = mp3read(FILE,N,MONO,DOWNSAMP)   Read MP3 audio file
0003 %       FILE is an MP3 audio file name.  Optional scalar N limits the number
0004 %       of frames to read, or, if a two-element vector, specifies
0005 %       the first and last frames to read.
0006 %       Optional flag MONO forces result to be mono if nonzero;
0007 %       Optional factor DOWNSAMP performs downsampling by 2 or 4.
0008 %       Y returns the audio data, one channel per column; FS is the
0009 %       sampling rate.  NBITS is the bit depth (always 16).
0010 %       OPTS.fmt is a format info string.
0011 % 2003-07-20 dpwe@ee.columbia.edu  This version calls mpg123.
0012 % 2004-08-31 Fixed to read whole files correctly
0013 % 2004-09-08 Uses mp3info to get info about mp3 files too
0014 % 2004-09-18 Reports all mp3info fields in OPTS.fmt; handles MPG2LSF sizes
0015 %            + added MONO, DOWNSAMP flags, changed default behavior.
0016 % 2005-04-11 added -r m for report of median VBR in mp3info (thx Merrie Morris)
0017 % 2006-01-09 Petr Janata - fixed argument list to mpg123 (see below).  Allowed
0018 %            passing N = [];
0019 % 2011-07-01 PJ - mpg123 would sometimes return insufficient data when only
0020 %            a partial read was requested, so a bit extra is being requested now
0021 % 2014-08-20 PJ - added dynamic mpg123, mp3info location based on
0022 %                 architecture
0023 % $Header: /homes/dpwe/matlab/columbiafns/RCS/mp3read.m,v 1.7 2005/04/11 20:55:16 dpwe Exp $
0024 
0025 if nargin < 2
0026   N = 0;
0027 else
0028   if isempty(N)
0029     N = 0;
0030   elseif length(N) == 1
0031     % Specified N was upper limit
0032     N = [1 N];
0033   end
0034 end
0035 if nargin < 3
0036   forcemono = 0;
0037 else
0038   forcemono = (MONO ~= 0);
0039 end
0040 if nargin < 4
0041   downsamp = 1;
0042 else
0043   downsamp = DOWNSAMP;
0044 end
0045 if downsamp ~= 1 && downsamp ~= 2 && downsamp ~= 4
0046   error('DOWNSAMP can only be 1, 2, or 4');
0047 end
0048 
0049 %%%%%%% Hard-coded behavior
0050 %% What factor should we downsample by?  (1 = no downsampling, 2 = half, 4=qtr)
0051 %downsamp = 4;
0052 %% Do we want to force the data to be single channel? (1 = yes, 0= keep orig)
0053 %forcemono = 1;
0054 
0055 %%%%%% Location of the binaries
0056 arch = computer('arch');
0057 if strcmp(arch,'win32')
0058    fpath = fileparts(which(mfilename));
0059    mp3_toolbox_path = fullfile(fpath,'mp3_toolbox');
0060    if exist(mp3_toolbox_path)
0061      mpg123 = fullfile(mp3_toolbox_path,'mpg123');
0062      mp3info = fullfile(mp3_toolbox_path,'mp3info');
0063    else
0064      error('Cannot locate mpg123 and mp3info!')
0065    end
0066 else
0067   mpg123 = '/usr/local/bin/mpg123';
0068   mp3info = '/usr/local/bin/mp3info';
0069 end
0070 
0071 %%%%%% Constants
0072 NBITS=16;
0073 
0074 %%%%%% Probe file to find format, size, etc. using "mp3info" utility
0075 cmd = [mp3info, ' -r m -p "%Q %u %r %v * %C %e %E %L %O %o %p" "', FILE,'"'];
0076 % Q = samprate, u = #frames, r = bitrate, v = mpeg version (1/2/2.5)
0077 % C = Copyright, e = emph, E = CRC, L = layer, O = orig, o = mono, p = pad
0078 w = mysystem(cmd);
0079 if isempty(w) && exist(FILE,'file')
0080     trylim = 20;
0081     tries = 0;
0082     pauseval = 2;
0083     fprintf(1,'mp3info error, retrying %d times\n',trylim);
0084     while isempty(w)
0085       tries = tries+1;
0086       pause(pauseval);
0087       fprintf(1,'attempt %d after %0.2fs pause\n',tries,pauseval);
0088       w = mysystem(cmd);
0089       if tries == trylim
0090           error('%s found, but %s is not loading it',FILE,mp3info)
0091       end
0092     end % while isempty(W
0093 end % if isempty(w) & exist(FILE,'file
0094     
0095 % Break into numerical and ascii parts by finding the delimiter we put in
0096 starpos = strfind(w,'*');
0097 nums = str2num(w(1:(starpos - 2)));
0098 strs = tokenize(w((starpos+2):end));
0099 
0100 SR = nums(1);
0101 nframes = nums(2);
0102 nchans = 2 - strcmp(strs{6}, 'mono');
0103 layer = length(strs{4});
0104 bitrate = nums(3)*1000;
0105 mpgv = nums(4);
0106 % Figure samples per frame, after
0107 % http://board.mp3-tech.org/view.php3?bn=agora_mp3techorg&key=1019510889
0108 if layer == 1
0109   smpspfrm = 384;
0110 elseif SR < 32000 && layer ==3
0111   smpspfrm = 576;
0112   if mpgv == 1
0113     error('SR < 32000 but mpeg version = 1');
0114   end
0115 else
0116   smpspfrm = 1152;
0117 end
0118 
0119 OPTS.fmt.mpgBitrate = bitrate;
0120 OPTS.fmt.mpgVersion = mpgv;
0121 % fields from wavread's OPTS
0122 OPTS.fmt.nAvgBytesPerSec = bitrate/8;
0123 OPTS.fmt.nSamplesPerSec = SR;
0124 OPTS.fmt.nChannels = nchans;
0125 OPTS.fmt.nBlockAlign = smpspfrm/SR*bitrate/8;
0126 OPTS.fmt.nBitsPerSample = NBITS;
0127 OPTS.fmt.mpgNFrames = nframes;
0128 OPTS.fmt.mpgCopyright = strs{1};
0129 OPTS.fmt.mpgEmphasis = strs{2};
0130 OPTS.fmt.mpgCRC = strs{3};
0131 OPTS.fmt.mpgLayer = strs{4};
0132 OPTS.fmt.mpgOriginal = strs{5};
0133 OPTS.fmt.mpgChanmode = strs{6};
0134 OPTS.fmt.mpgPad = strs{7};
0135 OPTS.fmt.mpgSampsPerFrame = smpspfrm;
0136 
0137 if SR == 16000 && downsamp == 4
0138   error('mpg123 will not downsample 16 kHz files by 4 (only 2)');
0139 end
0140 
0141 % 01/09/06 Petr Janata - changed downsampstr to be empty if downsamp rate is
0142 % 1. This prevents only one channel being written when -1 is used to designate
0143 % single channel writing in mpg123.
0144 
0145 if downsamp == 1
0146   downsampstr = '';
0147 else
0148   downsampstr = [' -',num2str(downsamp)];
0149 end
0150 FS = SR/downsamp;
0151 
0152 if forcemono == 1
0153   nchans = 1;
0154   chansstr = ' -m';
0155 else
0156   chansstr = '';
0157 end
0158 
0159 % Size-reading version
0160 if strcmp(N,'size') == 1
0161    Y = [floor(smpspfrm*nframes/downsamp), nchans];
0162 else
0163 
0164   % Temporary file to use
0165   tmpstub = sprintf('tmp%s.wav',num2str(round(1000*rand(1)))); 
0166   if strcmp(computer,'PCWIN')
0167     tmpdir = fullfile(FILE(1:regexp(FILE,filesep)-1),'TMP');
0168     if ~exist(tmpdir,'dir')
0169       mkdir(tmpdir)
0170     end
0171     tmpfile = fullfile(tmpdir,tmpstub);
0172   else
0173     tmpfile = fullfile('/tmp',tmpstub);
0174   end
0175 
0176   skipx = 0;
0177   skipblks = 0;
0178   skipstr = '';
0179   sttfrm = N(1)-1;
0180   if sttfrm > 0
0181     skipblks = floor(sttfrm*downsamp/smpspfrm);
0182     skipx = sttfrm - (skipblks*smpspfrm/downsamp);
0183     skipstr = [' -k ', num2str(skipblks)];
0184   end
0185 
0186   lenstr = '';
0187   endfrm = -1;
0188   if length(N) > 1
0189     endfrm = N(2);
0190     if endfrm > sttfrm
0191       decblk = ceil(endfrm*downsamp/smpspfrm) - skipblks + 1; % 01Jul2011 PJ - added 1 to ensure sufficient length read
0192       lenstr = [' -n ', num2str(decblk)];
0193     end
0194   end
0195 
0196   % Run the decode
0197   cmd=[mpg123, downsampstr, chansstr, skipstr, lenstr, ' -q -w ', tmpfile, ' ', '"',FILE,'"'];
0198   %disp(cmd);
0199   w = mysystem(cmd);
0200 
0201   % Load the data
0202   [Y,SR] = wavread(tmpfile);
0203 
0204   % Delete tmp file
0205   if strcmp(computer,'PCWIN')
0206     delete(tmpfile);
0207   else
0208     mysystem(['rm ', tmpfile]);
0209   end
0210   
0211   % Select the desired part
0212   if endfrm > sttfrm
0213     Y = Y(skipx+[1:(endfrm-sttfrm)],:);
0214   elseif skipx > 0
0215     Y = Y((skipx+1):end,:);
0216   end
0217 
0218 end
0219 
0220 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0221 function w = mysystem(cmd)
0222 % Run system command; report error; strip all but last line
0223 [s,w] = system(cmd);
0224 if s ~= 0 
0225   error(['unable to execute ',cmd]);
0226 end
0227 % Keep just final line
0228 w = w((1+max([0,findstr(w,10)])):end);
0229 % Debug
0230 %disp([cmd,' -> ','*',w,'*']);
0231 
0232 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0233 function a = tokenize(s)
0234 % Break space-separated string into cell array of strings
0235 % 2004-09-18 dpwe@ee.columbia.edu
0236 a = [];
0237 p = 1;
0238 n = 1;
0239 l = length(s);
0240 nss = findstr([s(p:end),' '],' ');
0241 for ns = nss
0242   % Skip initial spaces
0243   if ns == p
0244     p = p+1;
0245   else
0246     if p <= l
0247       a{n} = s(p:(ns-1));
0248       n = n+1;
0249       p = ns+1;
0250     end
0251   end
0252 end
0253

Generated on Wed 20-Sep-2023 04:00:50 by m2html © 2003