diff toolboxes/mp3readwrite/mp3write.m @ 0:e9a9cd732c1e tip

first hg version after svn
author wolffd
date Tue, 10 Feb 2015 15:05:51 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toolboxes/mp3readwrite/mp3write.m	Tue Feb 10 15:05:51 2015 +0000
@@ -0,0 +1,173 @@
+function mp3write(D,SR,NBITS,FILE,OPTIONS)
+% MP3WRITE   Write MP3 file by use of external binary
+%   MP3WRITE(Y,FS,NBITS,FILE) writes waveform data Y to mp3-encoded
+%     file FILE at sampling rate FS using bitdepth NBITS.  
+%     The syntax exactly mirrors WAVWRITE.  NBITS must be 16.
+%   MP3WRITE(Y,FS,FILE) assumes NBITS is 16
+%   MP3WRITE(Y,FILE) further assumes FS = 8000.
+%
+%   MP3WRITE(..., OPTIONS) specifies additional compression control 
+%     options as a string passed directly to the lame encoder
+%     program; default is '--quiet -h' for high-quality model.
+%
+%   Example: 
+%   To convert a wav file to mp3 (assuming the sample rate is 
+%   supported):
+%     [Y,FS] = wavread('piano.wav');
+%     mp3write(Y,FS,'piano.mp3');
+%   To force lame to use 160 kbps (instead of default 128 kbps)
+%   with the default filename extension (mp3):
+%     mp3write(Y,FS,'piano','--quiet -h -b 160');
+%
+%   Note: The actual mp3 encoding is done by an external binary, 
+%     lame, which is available for multiple platforms.  Usable
+%     binaries are available from:
+%     http://labrosa.ee.columbia.edu/matlab/mp3read.html
+%
+%   Note: MP3WRITE will use the mex file popenw, if available, to
+%     open a pipe to the lame encoder.  Otherwise, it will have to
+%     write a large temporary file, then execute lame on that file.
+%     popenw is available at: 
+%       http://labrosa.ee.columbia.edu/matlab/popenrw.html
+%     This is a nice way to save large audio files as the
+%     incremental output of your code, but you'll have to adapt the
+%     central loop of this function (rather than using it directly).
+%
+%   See also: mp3read, wavwrite, popenw.
+
+% 2005-11-10 Original version
+% 2007-02-04 Modified to exactly match wavwrite syntax, and to
+%   automatically find architecture-dependent binaries.
+% 2007-07-26 Writing of stereo files via tmp file fixed (thx Yu-ching Lin)
+%
+% $Header: /Users/dpwe/matlab/columbiafns/RCS/mp3write.m,v 1.2 2007/07/26 15:09:16 dpwe Exp $
+
+% find our baseline directory
+[path] = fileparts(which('mp3write'));
+
+% %%%%% Directory for temporary file (if needed)
+% % Try to read from environment, or use /tmp if it exists, or use CWD
+tmpdir = getenv('TMPDIR');
+if isempty(tmpdir) || exist(tmpdir,'file')==0
+  tmpdir = '/tmp';
+end
+if exist(tmpdir,'file')==0
+  tmpdir = '';
+end
+% ensure it exists
+%if length(tmpdir) > 0 && exist(tmpdir,'file')==0
+%  mkdir(tmpdir);
+%end
+
+%%%%%% Command to delete temporary file (if needed)
+rmcmd = 'rm';
+
+%%%%%% Location of the binary - attempt to choose automatically
+%%%%%% (or edit to be hard-coded for your installation)
+ext = lower(computer);
+if ispc
+  ext = 'exe';
+  rmcmd = 'del';
+end
+lame = fullfile(path,['lame.',ext]);
+
+%%%% Process input arguments
+% Do we have NBITS?
+mynargin = nargin;
+if ischar(NBITS)
+  % NBITS is a string i.e. it's actually the filename
+  if mynargin > 3
+    OPTIONS = FILE;
+  end
+  FILE = NBITS;
+  NBITS = 16;
+  % it's as if NBITS had been specified...
+  mynargin = mynargin + 1;
+end
+
+if mynargin < 5
+  OPTIONS = '--quiet -h';  % -h means high-quality psych model
+end
+
+[nr, nc] = size(D);
+if nc < nr
+  D = D';
+  [nr, nc] = size(D);
+end
+% Now rows are channels, cols are time frames (so interleaving is right)
+
+%%%%% add extension if none (like wavread)
+[path,file,ext] = fileparts(FILE);
+if isempty(ext)
+  FILE = [FILE, '.mp3'];
+end
+
+nchan = nr;
+nfrm = nc;
+
+if nchan == 1
+  monostring = ' -m m';
+else
+  monostring = '';
+end
+
+lameopts = [' ', OPTIONS, monostring, ' '];
+
+%if exist('popenw') == 3
+if length(which('popenw')) > 0
+
+  % We have the writable stream process extensions
+  cmd = ['"',lame,'"', lameopts, '-r -s ',num2str(SR),' - "',FILE,'"'];
+
+  p = popenw(cmd);
+  if p < 0
+    error(['Error running popen(',cmd,')']);
+  end
+
+  % We feed the audio to the encoder in blocks of <blksize> frames.
+  % By adapting this loop, you can create your own code to 
+  % write a single, large, MP3 file one part at a time.
+  
+  blksiz = 10000;
+
+  nrem = nfrm;
+  base = 0;
+
+  while nrem > 0
+    thistime = min(nrem, blksiz);
+    done = popenw(p,32767*D(:,base+(1:thistime)),'int16be');
+    nrem = nrem - thistime;
+    base = base + thistime;
+    %disp(['done=',num2str(done)]);
+  end
+
+  % Close pipe
+  popenw(p,[]);
+
+else 
+  disp('Warning: popenw not available, writing temporary file');
+  
+  tmpfile = fullfile(tmpdir,['tmp',num2str(round(1000*rand(1))),'.wav']);
+
+  wavwrite(D',SR,tmpfile);
+  
+  cmd = ['"',lame,'"', lameopts, '"',tmpfile, '" "', FILE, '"'];
+
+  mysystem(cmd);
+
+  % Delete tmp file
+  mysystem([rmcmd, ' "', tmpfile,'"']);
+
+end 
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+function w = mysystem(cmd)
+% Run system command; report error; strip all but last line
+[s,w] = system(cmd);
+if s ~= 0 
+  error(['unable to execute ',cmd,' (',w,')']);
+end
+% Keep just final line
+w = w((1+max([0,findstr(w,10)])):end);
+% Debug
+%disp([cmd,' -> ','*',w,'*']);