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