function [D, SR] = audioread(FN, TARGETSR, FORCEMONO, START, DUR)
% [D, SR] = audioread(FN, TARGETSR, FORCEMONO, START, DUR)
%   Read in an audio file, using wavread, mp3read, m4aread, or flacread as
%   appropriate. 
% 2010-09-16 Dan Ellis dpwe@ee.columbia.edu
% $Header: /Users/dpwe/matlab/columbiafns/audioread/RCS/audioread.m,v 1.4 2014/04/16 12:53:20 dpwe Exp dpwe $

if nargin < 2; TARGETSR = []; end
if nargin < 3; FORCEMONO = 0; end
if nargin < 4; START = 0; end
if nargin < 5; DUR = 0; end

END = START+DUR;

if length(TARGETSR) == 0
  TARGETSR = 0;
end

if length(FN) > 2 && FN(1) == '~' && FN(2) == '/'
  % tilde substitution
  FN = [getenv('HOME'),FN(2:end)];
end

overnet = 0;
if length(FN) >= 7
  overnet = strcmp(FN(1:7), 'http://');
end

if ~overnet && exist(FN, 'file') == 0
  error(['audioread: file ',FN,' not found']);
end

[pth,nam,ext] = fileparts(FN);
ext = lower(ext);

ismp3 = strcmp(ext,'.mp3');
ism4a = strcmp(ext, '.m4a') || strcmp(ext, '.aac') || strcmp(ext, '.mp4');
iswav = strcmp(ext, '.wav');
isrds = strcmp(ext, '.wv1') || strcmp(ext, '.wv2') ...
        || strcmp(ext, '.wvs') || strcmp(ext, '.shn') ...
        || strcmp(ext, '.aif') || strcmp(ext, '.aiff') ...
        || strcmp(ext, '.sph');
isflac = strcmp(ext, '.flac');

try
  if ismp3 || ism4a || iswav || isrds || isflac
    if ismp3
      [SIZ,SR] = mp3read(FN,'size');
    elseif ism4a
      [SIZ,SR] = m4aread(FN,'size');
    elseif iswav
      try
        [SIZ,SR] = wavread(FN,'size');
      catch me
        % WAV format that wavread rejects - use ReadSouand
        SIZ = [-1 0];
        [D,SR] = ReadSound(FN,1);
      end
    elseif isflac
      [SIZ,SR] = flacread(FN,'size');
    else
      % ReadSound has no 'size' function
      SIZ = [-1 0];
      % but we really want to know the SR - read one sample
      [D,SR] = ReadSound(FN,1);
    end

    ds = 1;
    % apply downsampling during read to minimize core usage
    % (not supported in ReadSound)
    if ~isrds && TARGETSR > 0 && SR >= 2*TARGETSR
      ds = 2;
      if SR >= 4*TARGETSR && (SR >= 22050 || ~ismp3)
        % mpg123 will only do 4:1 downsampling for higher SRs
        ds = 4;
      end
    end
    % apply truncation during read to avoid massive core usage
  %  N = 0;
  %  if START > 0 || END > START
      SIX = max(1,round(START*SR/ds)+1);
      if ~ismp3 && ~ism4a && END <= START && SIZ(1)>0; END = SIZ(1)/SR; end
  %    if END > START
        % sample indices, post resampling
        EIX = round(END*SR/ds);
        if SIZ(1) > 0
          EIX = min(floor(SIZ(1)/ds),EIX);
        end
        N = [SIX EIX];
  %    end
  %  end
    %disp(['N=',num2str(N),' MONO=',num2str(FORCEMONO),' ds=',num2str(ds)]);
    if ismp3
      [D,SR] = mp3read(FN,N,FORCEMONO,ds);
    elseif ism4a
      [D,SR] = m4aread(FN,N,FORCEMONO,ds);
    elseif iswav
      try
        [D,SR] = wavread_downsamp(FN,N,FORCEMONO,ds);
      catch me
        % WAV format that wavread rejects - use ReadSouand
        if N(2) < 0
          LEN = -1;
        else
          LEN = N(2) - N(1) + 1;
        end
        [D,SR] = ReadSound(FN,LEN*ds,N(1)*ds-1);
        D = D'; % returns in rows!
      end
    elseif isflac
      [D,SR] = flacread(FN,N,FORCEMONO,ds);
    else % ReadSound
      if N(2) < 0
        LEN = -1;
      else
        LEN = N(2) - N(1) + 1;
      end
      [D,SR] = ReadSound(FN,LEN*ds,N(1)*ds-1);
      D = D'; % returns in rows!
    end
  else
    % Handlers that do not support specifying subranges of samples go here
  %  if strcmp(ext, '.flac')
  %    [D,SR] = flacread2(FN);
  %  else
    if 1
      error(['audioread: cannot figure type of file ',FN]);
    end
    % truncate before resampling
    if START > 0 || (END > START && END < length(D)/SR)
      if END < START; END = length(D)/SR; end
      EIX = min(length(D),round(END*SR));
      D = D((round(START*SR)+1):EIX,:);
    end
  end
  
catch me
  % most likely a problem reading sound files
  disp(['*** audioread: problem reading ', FN, ':', me.message]);
  disp(['*** audioread: returning empty waveform']);
  D = [];
  SR = TARGETSR;
end

% always mono (if not handled in mp3read etc.)
[nsamp,nchan] = size(D);
if FORCEMONO && nchan > 1
  D = mean(D,2);
end

if TARGETSR > 0 && SR ~= TARGETSR && nsamp > 1
  [p,n,e] = fileparts(FN);
%  disp(['*** audioread: resampling ',n,' from ', num2str(SR), ...
%        ' to ', num2str(TARGETSR)]);
  D = resample(D, TARGETSR, SR);
  SR = TARGETSR;
end

%disp(['audioread(',FN,',',num2str(TARGETSR),',',num2str(FORCEMONO),',',num2str(START),',',num2str(DUR),')->',num2str(size(D)),'@',num2str(SR)]);