Mercurial > hg > smallbox
changeset 166:1495bdfa13e9 danieleb
Updated grassmanian function (restored old computation of the dictionary) and added functions to the audio class
author | Daniele Barchiesi <daniele.barchiesi@eecs.qmul.ac.uk> |
---|---|
date | Mon, 19 Sep 2011 14:53:23 +0100 |
parents | 88578ec2f94a |
children | 8324c7ea6602 |
files | util/classes/@audio/audio.m util/classes/@audio/buffer.m util/classes/@audio/plot.m util/classes/@audio/unbuffer.m util/classes/dictionaryMatrices/grassmannian.m |
diffstat | 5 files changed, 197 insertions(+), 94 deletions(-) [+] |
line wrap: on
line diff
--- a/util/classes/@audio/audio.m Wed Aug 31 13:52:23 2011 +0100 +++ b/util/classes/@audio/audio.m Mon Sep 19 14:53:23 2011 +0100 @@ -1,54 +1,63 @@ classdef audio - %% Audio object - properties - s %vector containing the audio signal - fs %sampling frequency - nBits % number of bits per sample - name % string containing the name of the audio file - format % string containing the format of the audio file - end - - methods - %% Constructor - function obj = audio(varargin) - error(nargchk(1,5,nargin)); - if ischar(varargin{1}) - [~, obj.name obj.format] = fileparts(varargin{1}); - switch obj.format - case '.wav' - [obj.s obj.fs obj.nBits] = wavread(varargin{1}); - otherwise - error('Unsupported audio format') - end - else - obj.s = varargin{1}; - if nargin>1, obj.fs = varargin{2}; else obj.fs = []; end - if nargin>2, obj.nBits = varargin{3}; else obj.nBits = []; end - if nargin>3, obj.name = varargin{4}; else obj.name = []; end - if nargin>4, obj.format = varargin{5}; else obj.format = []; end - end - end - - %% Playback functions - function player = play(obj, player) - if ~exist('player','var') || isempty(player) - player = audioplayer(obj.s,obj.fs); - end - play(player); - end - - function player = stop(obj, player) - if ~exist('player','var') || isempty(player) - player = audioplayer(obj.s,obj.fs); - end - stop(player) - end - - function player = pause(obj, player) - if ~exist('player','var') || isempty(player) - player = audioplayer(obj.s,obj.fs); - end - pause(player) - end - end + %% Audio object + properties + s %vector containing the audio signal + S %matrix containing frames of audio for subsequent processing + fs %sampling frequency + nBits %number of bits per sample + name %string containing the name of the audio file + format %string containing the format of the audio file + bufferOperator %struct containing the parameters of the buffer operator (used by unbuffer to invert it) + end + + methods + %% Constructor + function obj = audio(varargin) + % if no arguments are specified, prompt for the choice of an + % audio file + if ~nargin + [fileName,pathname] = uigetfile({'*.wav; *.aiff;'},'Select an audio file'); + varargin{1} = strcat(pathname,filesep,fileName); + end + if ischar(varargin{1}) + [~, obj.name obj.format] = fileparts(varargin{1}); + switch obj.format + case '.wav' + [obj.s obj.fs obj.nBits] = wavread(varargin{1}); + otherwise + error('Unsupported audio format') + end + else + obj.s = varargin{1}; + if nargin>1, obj.fs = varargin{2}; else obj.fs = []; end + if nargin>2, obj.nBits = varargin{3}; else obj.nBits = []; end + if nargin>3, obj.name = varargin{4}; else obj.name = []; end + if nargin>4, obj.format = varargin{5}; else obj.format = []; end + end + obj.S = []; + obj.bufferOperator = []; + end + + %% Playback functions + function player = play(obj, player) + if ~exist('player','var') || isempty(player) + player = audioplayer(obj.s,obj.fs); + end + play(player); + end + + function player = stop(obj, player) + if ~exist('player','var') || isempty(player) + player = audioplayer(obj.s,obj.fs); + end + stop(player) + end + + function player = pause(obj, player) + if ~exist('player','var') || isempty(player) + player = audioplayer(obj.s,obj.fs); + end + pause(player) + end + end end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/util/classes/@audio/buffer.m Mon Sep 19 14:53:23 2011 +0100 @@ -0,0 +1,27 @@ +function obj = buffer(obj,wLength,overlap,window,method) + +%% Check inputs & Defaults +error(nargchk(2, 5, nargin, 'struct')); + +if ~exist('overlap','var') || isempty(overlap), overlap = 0; end +if ~exist('method','var') || isempty(method), method = 'standard'; end + +%% Buffer audio +switch lower(method) + case 'standard' + if ~exist('window','var') || isempty(window), window = @rectwin; end + validWindows = {'hanning','hamming','triang','rectwin'}; + if ~sum(strcmpi(validWindows,func2str(window))); + error('The window chosen is not valid because it cannot be inverted!'); + end + obj.S = diag(window(wLength))*buffer(obj.s,wLength,overlap,'nodelay'); + case 'lot' + if ~exist('window','var') || isempty(window), window = 'sin2'; end + s_lot = lot(obj.s,wLength,'id',overlap,window); + obj.S = buffer(s_lot,wLength); + otherwise + error('Please specify a valid buffer method'); +end + +obj.bufferOperator = struct('wLength',wLength,'overlap',... + overlap,'window',window,'method',method);
--- a/util/classes/@audio/plot.m Wed Aug 31 13:52:23 2011 +0100 +++ b/util/classes/@audio/plot.m Mon Sep 19 14:53:23 2011 +0100 @@ -1,58 +1,95 @@ function plot(obj) +figure, +playbackPanelH = uipanel(gcf,'Units','Normalized','Position',[.3 0 .4 .1]); + +buttWidth = 1/6; +centers = linspace(0,1,7)-buttWidth/2; +rewButtonH = uicontrol(playbackPanelH,'Style','pushbutton','String','<<','Units',... + 'Normalized','Position',[centers(2) 0.2 buttWidth 0.6]); +ffButtonH = uicontrol(playbackPanelH,'Style','togglebutton','String','>>','Units',... + 'Normalized','Position',[centers(3) 0.2 buttWidth 0.6]); +stopButtonH = uicontrol(playbackPanelH,'Style','pushbutton','String','stop','Units',... + 'Normalized','Position',[centers(4) 0.2 buttWidth 0.6]); +playButtonH = uicontrol(playbackPanelH,'Style','togglebutton','String','play','Units',... + 'Normalized','Position',[centers(5) 0.2 buttWidth 0.6]); +pauseButtonH = uicontrol(playbackPanelH,'Style','togglebutton','String','||','Units',... + 'Normalized','Position',[centers(6) 0.2 buttWidth 0.6]); + +waveformPanelH = uipanel(gcf,'Units','Normalized','Position',[.02 .12 .96 .86]); +waveformAxesH = axes('Parent',waveformPanelH); + %% Plot the time domain signal s = obj.s; fs = obj.fs; -figure, plot((1:length(s))/fs,s); +plot((1:length(s))/fs,s); title('Audio signal') xlabel('time (s)'); axis tight player = audioplayer(s,fs); +set(player,'TimerPeriod',0.1); set(player,'StartFcn',@plotTransportBar); set(player,'TimerFcn',@updateTransportBar); set(player,'StopFcn',@deleteTransportBar); -%% Add playbaack controls -playButtonH = uicontrol(gcf,'Style','pushbutton','String','play','Units',... - 'Normalized','Position',[0.02 + 0.39 0 0.1 0.05]); -stopButtonH = uicontrol(gcf,'Style','pushbutton','String','stop','Units',... - 'Normalized','Position',[0.12 + 0.39 0 0.1 0.05]); - +%% Add playback controls set(playButtonH,'Callback',@play_callback); set(stopButtonH,'Callback',@stop_callback); +set(pauseButtonH,'Callback',@pause_callback); +set(rewButtonH,'Callback',@rew_callback); +set(ffButtonH,'Callback',@ff_callback); - function play_callback(~,~) - if strcmpi(get(playButtonH,'String'),'play') - play(player,player.CurrentSample); - set(playButtonH,'String','pause'); - else - pause(player) - set(playButtonH,'String','play'); - end - end + function play_callback(~,~) + set(player,'SampleRate',fs); + play(player,player.CurrentSample); + set(pauseButtonH,'Value',0); + set(ffButtonH,'Value',0); + end - function stop_callback(~,~) - stop(player); - end + function pause_callback(~,~) + pause(player); + set(playButtonH,'Value',0); + set(ffButtonH,'Value',0); + end + + function stop_callback(~,~) + stop(player); + set(playButtonH,'Value',0); + set(pauseButtonH,'Value',0); + set(ffButtonH,'Value',0); + end + + function ff_callback(~,~) + set(player,'SampleRate',1.5*fs); + set(pauseButtonH,'Value',0); + set(playButtonH,'Value',0); + end + + function rew_callback(~,~) + stop(player); + play(player); + set(pauseButtonH,'Value',0); + set(playButtonH,'Value',1); + end %% Transport Bar functions - function plotTransportBar(~,~) - global tbH - xLim = get(gca,'Xlim'); - yLim = get(gca,'YLim'); - tbH = line([xLim(1) xLim(1)],yLim,'Color','k'); - end - - function updateTransportBar(hObject,~) - global tbH - currentSample = hObject.CurrentSample; - pos = currentSample/fs; - set(tbH,'XData',[pos pos]); - end + function plotTransportBar(~,~) + global tbH + xLim = get(gca,'Xlim'); + yLim = get(gca,'YLim'); + tbH = line([xLim(1) xLim(1)],yLim,'Color','k'); + end - function deleteTransportBar(~,~) - global tbH - delete(tbH); - end + function updateTransportBar(hObject,~) + global tbH + currentSample = hObject.CurrentSample; + pos = currentSample/fs; + set(tbH,'XData',[pos pos]); + end + + function deleteTransportBar(~,~) + global tbH + delete(tbH); + end end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/util/classes/@audio/unbuffer.m Mon Sep 19 14:53:23 2011 +0100 @@ -0,0 +1,27 @@ +function s = unbuffer(obj) + +%% Check inputs and Defaults +if ~isprop(obj,'bufferOperator') || isempty(obj.bufferOperator) + error('You must buffer a signal before unbuffer it, come on!'); +end + +switch lower(obj.bufferOperator.method) + %Unbuffer using overlap-add method + case 'standard' + w = obj.bufferOperator.window(obj.bufferOperator.wLength); + S = diag(1./w)*obj.S; + %Non overlapping case + if obj.bufferOperator.overlap == 0 + s = S(:); + %Overlapping case + else + Stemp = S(1:obj.bufferOperator.wLength-obj.bufferOperator.overlap,1:end); + s = [Stemp(:); S(obj.bufferOperator.wLength-obj.bufferOperator.overlap+1:end,end)]; + end + %Unbuffer using inverse lot with identity local transform + case 'lot' + s = ilot(obj.S(:),obj.bufferOperator.wLength,'id',... + obj.bufferOperator.overlap,obj.bufferOperator.window); + otherwise + error('Please specify a valid buffer method'); +end
--- a/util/classes/dictionaryMatrices/grassmannian.m Wed Aug 31 13:52:23 2011 +0100 +++ b/util/classes/dictionaryMatrices/grassmannian.m Mon Sep 19 14:53:23 2011 +0100 @@ -4,18 +4,21 @@ % % [A G res] = grassmanian(n,m,nIter,dd1,dd2,initA) % -% +% REFERENCE +% M. Elad, Sparse and Redundant Representations, Springer 2010. + %% Parameters and Defaults error(nargchk(2,7,nargin)); if ~exist('verb','var') || isempty(verb), verb = false; end %verbose output if ~exist('initA','var') || isempty(initA), initA = randn(n,m); end %initial matrix -if ~exist('dd2','var') || isempty(dd2), dd2 = 0.95; end %shrinking factor +if ~exist('dd2','var') || isempty(dd2), dd2 = 0.99; end %shrinking factor if ~exist('dd1','var') || isempty(dd1), dd1 = 0.9; end %percentage of coherences to be shrinked if ~exist('nIter','var') || isempty(nIter), nIter = 10; end %number of iterations %% Main algo A = normc(initA); %normalise columns +[Uinit Sigma] = svd(A); G = A'*A; %gram matrix muMin = sqrt((m-n)/(n*(m-1))); %Lower bound on mutual coherence (equiangular tight frame) @@ -40,12 +43,12 @@ end % [~, Sigma_gram V_gram] = svd(G); %calculate svd decomposition of gramian -% Sigma_new = sqrt(Sigma_gram(1:n,:)).*sign(Sigma); %calculate singular values of dictionary -% A = Uinit*Sigma_new*V_gram'; %update dictionary + % A = normc(A); %normalise dictionary -[U S] = svd(G); %calculate svd decomposition of gramian -A = sqrt(S(1:n,1:n))*U(:,1:n)'; %calculate valid frame, s.t. A'*A=G +[V_gram Sigma_gram] = svd(G); %calculate svd decomposition of gramian +Sigma_new = sqrt(Sigma_gram(1:n,:)).*sign(Sigma); %calculate singular values of dictionary +A = Uinit*Sigma_new*V_gram'; %update dictionary % %% Debug visualization function % function plotcart2d(A)