view 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 source
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,'*']);