I connect my iPhone and matlab with the tcpip function.
I need to plot the data in real time (and before make some calculations with the data).
I used real_time_data_stream_plotting.m which I found in internet.
%% Real Time Data Stream Plotting Example
function real_time_data_stream_plotting
%%
% This example demonstrates how to automatically read a set number of data bytes as and
% when they are available. This MATLAB(R) script also generates a real time plot of streaming
% data collected from the TCPIP server.
%
% The script may be updated to use any instrument/device/TCPIP server
% to collect real time data. You may need to update the IP address and
% port.
%
% To generate a report of this entire script, you may use the PUBLISH
% command at the MATLAB(R) command line as follows:
%
% publish(real_time_data_plot);
% Author: Ankit Desai
% Copyright 2010 - The MathWorks, Inc.
%% Create the interface object
% Create a TCPIP object listening to port 19 (Character Generator).
%
% *Note* : To enable character generator service at port 19 on a Windows platform, enable:
%
% Control Panel > Add Remove Programs > Add/Remove Windows Component > Networking Services
%
interfaceObject = tcpip('192.168.1.111',52928);
%%
% Setup a figure window and define a callback function for close operation
figureHandle = figure('NumberTitle','off',...
'Name','Live Data Stream Plot',...
'Color',[0 0 0],...
'CloseRequestFcn',{#localCloseFigure,interfaceObject});
%%
% Setup the axes
axesHandle = axes('Parent',figureHandle,...
'YGrid','on',...
'YColor',[0.9725 0.9725 0.9725],...
'XGrid','on',...
'XColor',[0.9725 0.9725 0.9725],...
'Color',[0 0 0]);
xlabel(axesHandle,'Number of Samples');
ylabel(axesHandle,'Value');
%%
% Initialize the plot and hold the settings on
hold on;
plotHandle = plot(axesHandle,4,'-y','LineWidth',1);
%% Setup interface object to read chunks of data
% Set the number of bytes to read at a time
bytesToRead = 500;
%%
% Define a callback function to be executed when desired number of bytes
% are available in the input buffer
interfaceObject.BytesAvailableFcn = {#localReadAndPlot,plotHandle,bytesToRead};
interfaceObject.BytesAvailableFcnMode = 'byte';
interfaceObject.BytesAvailableFcnCount = bytesToRead;
%%
% Open the interface object
fopen(interfaceObject);
pause(3);
snapnow;
%% Implement the bytes available callback
function localReadAndPlot(interfaceObject,~,figureHandle,bytesToRead)
%%
% Read the desired number of data bytes
data = fread(interfaceObject,bytesToRead);
%%
% Update the plot
set(figureHandle,'Ydata',data);
%% Implement the close figure callback
function localCloseFigure(figureHandle,~,interfaceObject)
%%
% Clean up the interface object
fclose(interfaceObject);
delete(interfaceObject);
clear interfaceObject;
%%
% Close the figure window
delete(figureHandle);
My problem is that I have a plot in real time but I have no idea which data I am plotting. I know that the data that arrived from the iPhone are a matrix with 62 column (if I export the data from the iPhone directly I get a .csv file of 62 columns).
How can I choose with column I plot ?
Thank you very much!
Here would be my take on indexing the data only for the required column:
function real_time_data_stream_plotting()
% These can be very well arguments for the function
FRAME_SIZE = 62; % This many columns (each columns is one byte)
FRAME_COUNT = 500; % This much data to plot at once
DATA_COLUMN = 3 % Position of the plotted column
% Create connection
conn = tcpip('192.168.1.111', 52928);
% Set-up graphics
hf = figure( ...
'NumberTitle', 'off', ...
'Name', 'Live Data Stream Plot', ...
'Color', [0 0 0], ...
'CloseRequestFcn', {#localCloseFigure,conn} ...
);
ha = axes( ...
'Parent', hf,...
'YGrid', 'on', ...
'YColor', [0.9725 0.9725 0.9725], ...
'XGrid', 'on', ...
'XColor', [0.9725 0.9725 0.9725], ...
'Color', [0 0 0] ...
);
hold(ha, 'on');
xlabel(ha,'Number of Samples');
ylabel(ha,'Value');
hl = plot(ha, 4, '-r', 'LineWidth', 1);
% Set-up connection callback
conn.BytesAvailableFcn = {#update_plot, hl, FRAME_SIZE, FRAME_COUNT, DATA_COLUMN};
conn.BytesAvailableFcnMode = 'byte';
conn.BytesAvailableFcnCount = FRAME_SIZE * FRAME_COUNT;
% Open connection and exit
fopen(conn);
pause(3);
snapnow;
end
% -------- Local Functions --------
function update_plot(conn, ~, hl, frame_size, frame_count, data_column)
data = fread(conn, frame_count*frame_size);
data = data(data_column + frame_size*(0:frame_count-1));
set(hl, 'YData', data);
end
function clean_up_on_close(hf, ~, conn)
fclose(conn);
delete(conn);
clear conn;
delete(hf);
end
However, I don't feel comfortable posting code based on on copyrighted work...
Related
%%%%%%%%%%%%%%%
%%%%%% Loop through data 3 ms at a time (Live)
t_window = 3e-3;
ind_3_raw = t_window*fs; %%% Number of samples for 3 ms in raw data
ind_3_spec = ceil(t_window/(T(2)-T(1))); %%%% Number of samples for 3 ms in spectrogram
counter = 0; %%%% number of 3 ms windows from start of file
stay_in = 1; %%% change to zero when its time to break;
figure(2);
while stay_in
%%%% Make time series and spectrogram plot
if (((counter+1)*ind_3_raw)<length(t)) %%%% if last point is outside of data
subplot(211)
plot(t(counter*ind_3_raw+1:(counter+1)*ind_3_raw)*1e3,data_filt((counter*ind_3_raw+1:(counter+1)*ind_3_raw)),'k')
% plot(t(counter*ind_3_raw+1:(counter+1)*ind_3_raw),data((counter*ind_3_raw+1:(counter+1)*ind_3_raw)),'k')
xlabel('Time [ms]')
ylabel('A.U.')
% xlim([0 t(end)])
set(gca,'fontsize',16)
subplot(212)
imagesc(T(counter*ind_3_spec+1:(counter+30)*ind_3_spec)*1e3,F/1000,S_dB(:,counter*ind_3_spec+1:(counter+30)*ind_3_spec));
% imagesc(T(counter*ind_3_spec+1:(counter+1)*ind_3_spec),F/1000,S_dB(:,counter*ind_3_spec+1:(counter+1)*ind_3_spec));
% imagesc(T(counter*ind_3_spec+1:(counter+1)*ind_3_spec),F/1000,Sf_dB(:,counter*ind_3_spec+1:(counter+1)*ind_3_spec));
axis xy;
xlabel('Time [ms]')
ylabel('Frequency [kHz]')
% colorbar
caxis([30 60])
% caxis([40 80]) %%% caxis limits, might need to change this manually when needed
% xlim([0 T(end)])
colormap jet
set(gca,'fontsize',16)
counter = counter + 1; %%% increment counter
drawnow;
pause;
%%%% Get user input
else
stay_in = 1;
end
end
I want a pop up dialog box for user to input a 1 every time a sferic in data appears?
I am using bin2mat function from matlab file exchange, for some reason it runs very slow. Is it possible to make it run faster or is there an alternative? I am trying: zC = bin2mat(s.X,s.Y,s.Z,xC,yC); I am not sure where it gets bogged down. I need to do this on point cloud data to calculate volume and such.
Here is the code:
function ZG = bin2mat(x,y,z,XI,YI,varargin)
% BIN2MAT - create a matrix from scattered data without interpolation
%
% ZG = BIN2MAT(X,Y,Z,XI,YI) - creates a grid from the data
% in the (usually) nonuniformily-spaced vectors (x,y,z)
% using grid-cell averaging (no interpolation). The grid
% dimensions are specified by the uniformily spaced vectors
% XI and YI (as produced by meshgrid).
%
% ZG = BIN2MAT(...,#FUN) - evaluates the function FUN for each
% cell in the specified grid (rather than using the default
% function, mean). If the function FUN returns non-scalar output,
% the output ZG will be a cell array.
%
% ZG = BIN2MAT(...,#FUN,ARG1,ARG2,...) provides aditional
% arguments which are passed to the function FUN.
%
% EXAMPLE
%
% %generate some scattered data
% [x,y,z]=peaks(150);
% ind=(rand(size(x))>0.9);
% xs=x(ind); ys=y(ind); zs=z(ind);
%
% %create a grid, use lower resolution if
% %no gaps are desired
% xi=min(xs):0.25:max(xs);
% yi=min(ys):0.25:max(ys);
% [XI,YI]=meshgrid(xi,yi);
%
% %calculate the mean and standard deviation
% %for each grid-cell using bin2mat
% Zm=bin2mat(xs,ys,zs,XI,YI); %mean
% Zs=bin2mat(xs,ys,zs,XI,YI,#std); %std
%
% %plot the results
% figure
% subplot(1,3,1);
% scatter(xs,ys,10,zs,'filled')
% axis image
% title('Scatter Data')
%
% subplot(1,3,2);
% pcolor(XI,YI,Zm)
% shading flat
% axis image
% title('Grid-cell Average')
%
% subplot(1,3,3);
% pcolor(XI,YI,Zs)
% shading flat
% axis image
% title('Grid-cell Std. Dev.')
%
% SEE also RESHAPE ACCUMARRAY FEVAL
% A. Stevens 3/10/2009
% astevens#usgs.gov
%check inputs
error(nargchk(5,inf,nargin,'struct'));
%make sure the vectors are column vectors
x = x(:);
y = y(:);
z = z(:);
if all(any(diff(cellfun(#length,{x,y,z}))));
error('Inputs x, y, and z must be the same size');
end
%process optional input
fun=#mean;
test=1;
if ~isempty(varargin)
fun=varargin{1};
if ~isa(fun,'function_handle');
fun=str2func(fun);
end
%test the function for non-scalar output
test = feval(fun,rand(5,1),varargin{2:end});
end
%grid nodes
xi=XI(1,:);
yi=YI(:,1);
[m,n]=size(XI);
%limit values to those within the specified grid
xmin=min(xi);
xmax=max(xi);
ymin=min(yi);
ymax=max(yi);
gind =(x>=xmin & x<=xmax & ...
y>=ymin & y<=ymax);
%find the indices for each x and y in the grid
[junk,xind] = histc(x(gind),xi);
[junk,yind] = histc(y(gind),yi);
%break the data into a cell for each grid node
blc_ind=accumarray([yind xind],z(gind),[m n],#(x){x},{NaN});
%evaluate the data in each grid using FUN
if numel(test)>1
ZG=cellfun(#(x)(feval(fun,x,varargin{2:end})),blc_ind,'uni',0);
else
ZG=cellfun(#(x)(feval(fun,x,varargin{2:end})),blc_ind);
end
It is slower on these two steps for one run it took:
ZG=cellfun(#(x)(feval(fun,x,varargin{2:end})),blc_ind); took 33 secs
blc_ind=accumarray([yind xind],z(gind),[m n],#(x){x},{NaN}); took 10 secs
You can change blc_ind = ... to
ZG=accumarray([yind xind],z(gind),[m n],#mean,NaN);
and delete other codes form here so the is no need to if numel(test)>1....
Code which tries to mimic the real dynamic condition
clear all; close all;
hFig2=figure('Units','inches', 'Name', 'Time');
hax2=axes(hFig2);
movegui(hFig2, 'southeast');
index=1;
while (index < 7);
hFig2=figure(hFig2);
u=0:0.01:1+index;
plot(hax2, u); % Give columns 1xXYZ to Matlab
hold on;
axis(hax2, 'xy');
axis(hax2, [0 (size(u,2)/1 - 0) min(u) max(u)]); % to maximise size
axis(hax2, 'off'); % no ticks
index=index+1;
pause(1);
hold off;
drawnow
end;
Logs 1 hax2 in more dynamic condition,
Logs 2 hax2 mostly in Code
%% Logs 1 in dynamic condition with failure output
% Failure in more dynamic conditions because axes get deleted for some reason
% hax2
%
% hax2 =
%
% handle to deleted Axes
%
%% Logs 2 mostly in Code condition and correct because
% hax2 =
%
% Axes with properties:
%
% XLim: [0 201]
% YLim: [0 2]
% XScale: 'linear'
% YScale: 'linear'
% GridLineStyle: '-'
% Position: [0.1300 0.1100 0.7750 0.8150]
% Units: 'normalized'
Error if failure in hax2 i.e. handle to deleted axes for some reason
%% Failure message
% Show all properties
%
% Warning: MATLAB has disabled some advanced graphics rendering features by switching to software OpenGL. For more information, click
% here.
% Error using plot
% Invalid handle.
%
% Error in test_invalid_handle (line 12)
% plot(hax2, u);
Some tentative proposals of solutions
Save the axes handle at the end of each loop; possible related thread Save axes handle when plotting In MATLAB
...
OS: Debian 8.5 64 bit
Matlab: 2016a
Hardware: Asus Zenbook UX303UA
Linux kernel: 4.6 of backports
When calling axes, the first input should be a parameter/value pair that specifies the parent. If you pass it a single handle graphics input it assumes that input is a handle to an axes
axes(hFig2)
% Error using axes
% Invalid axes handle
Or as you have it written
hax2 = axes(hFig2);
% Error using axes
% Too many output arguments.
Because you are passing an invalid axes handle to it, it doesn't properly assign the handle to a new axes to hax2. It is likely that your deleted hax2 that you're seeing is from a previous run of the script.
Instead, you'll want to use parameter/value pairs to specify the Parent property of the axes.
hax2 = axes('Parent', hFig2);
Also, I would remove the extraneous call to figure every time through the loop since you explicitly specify the parent object of each plot object
I've attempted to look at MatLab documentation here:
http://www.mathworks.com/help/matlab/ref/interp3.html
and then in the
help interp3
section of MatLab, but I'm having trouble figuring out what I want actually and if interp3 is the thing that I'm looking for. But, I may just not be understanding if I'm able to use interp3 with the way I have things laid out as of now. I've attached a figure that I can create from a MatLab program that I wrote. It's taking NOAA lat/long (x/y), U/V directions for wind vectors, and then a Z value for the 2D levels to this field.
Using the format:
quiver3(x,y,z,u,v,w)
with the "W" component set to 0.
This is a very small section of the field, but what I'm trying to do is to interpolate between these 2D vector fields in order to create a 3D field.
Do I have to group U/X , V/Y, and W/Z into their own vectors in order to use interp3 ? I'm still not sure that the 3D function "V" section is in the interp3 syntax of
Vq = interp3(X,Y,Z,V,Xq,Yq,Zq)
This is a very small section of the field, but what I'm trying to do is to interpolate between these 2D vector fields in order to create a 3D field.
My code:
tic
clc
clear all
% You will have to change the directory to wherever you place the read_grib.r4
% file. In addition, It's necessary to have an external compiler connected
% to MatLab in order to build the mex-file that gives you the power to use
% the read_grib decoding. This is really tricky. On OSX I used Xcode as an
% environment and MatLab virtually worked immediately. On Windows, I have
% 2012(b) and had to use the call system('mxvc <BDS_unpack_mex5.c>') which
% utilized Microsoft's C-compiler that I had SOMEWHERE on my computer
% thankfully (may be pre-intalled). There are tutorials online for
% different compilers. In addition, if you're smart about it you can add
% the mex-file build to the start-up operations so you never have to worry
% about it, but my questionably legal MatLab copies seem to make this a
% little more difficult.
cd /Users/Sargent_PC/Downloads/read_grib.r4/
mex BDS_unpack_mex5.c
% ** Inventory doesn't need to be done every iteration **
% ** Uncomment the line below to get a record inventory **
%read_grib('NOAAdata.grb','inv');
% Creating a struct named "grib_struct" for each of the records I'm
% extracting out of the grib file. They exist in pairs with 6 records
% separating them. Should we want to extract ALL of the U and V wind
% components I'll iterate with a simple for-loop.
grib_struct=read_grib('NOAAdata.grb', [60,61,66,67]); %,72,73,78,79,84,85,90,91,96,97]);
UwindVec50mb = grib_struct(1).fltarray; %rec60
VwindVec50mb = grib_struct(2).fltarray; %rec61
UwindVec75mb = grib_struct(3).fltarray; %rec66
VwindVec75mb = grib_struct(4).fltarray; %rec67
% UwindVec100mb = grib_struct(5).fltarray; %rec72
% VwindVec100mb = grib_struct(6).fltarray; %rec73
% UwindVec125mb = grib_struct(7).fltarray; %rec78
% VwindVec125mb = grib_struct(8).fltarray; %rec79
% UwindVec150mb = grib_struct(9).fltarray; %rec84
% VwindVec150mb = grib_struct(10).fltarray; %rec85
% UwindVec175mb = grib_struct(11).fltarray; %rec90
% VwindVec175mb = grib_struct(12).fltarray; %rec91
% UwindVec200mb = grib_struct(13).fltarray; %rec96
% VwindVec200mb = grib_struct(14).fltarray; %rec97
%50mb range has records 60 and 61 for U and V respectively.
%75mb range has records 66 and 67 for U and V respectively.
%100mb range has records 72 and 73 for U and V respectively.
%125mb range has records 78 and 79 for U and V respectively.
%150mb range has records 84 and 85 for U and V respectively.
%175mb range has records 90 and 91 for U and V respectively.
%200mb range has records 96 and 97 for U and V respectively.
%These extracted sections of the grib file will read "extracted" on the
%left-hand side should they be successfully extracted.
load NOAAlatlongdata; % read the data into a matrix
lat_value = NOAAlatlongdata(:,3); % copy first column of NOAAlatlongdata into lat_value
long_value = NOAAlatlongdata(:,4); % and second column of NOAAlatlongdata into long_value
% I was going to add in a pressure to altitude change here, but
% it may be in our best interest to get a list of values for each
% pressure level that correspond to altitude and create our own
% vector of those values in order to simplify the calculations that
% the program has to do.
% z50mb_val = ;
% z75mb_val = ;
% z100mb_val= ;
% z125mb_val= ;
% z150mb_val= ;
% z175mb_val= ;
% z200mb_val= ;
% Creating vectors of the Z-values which are gotten from converting the
% pressure value to altitude. I feel like this is a very bulky way to do
% this, and I've included the tic-toc timing to show that it's ~30seconds
% per vector creation. For each altitude level that we add you'll add
% ~30seconds JUST to the vector creation component of the program.
tic; for i = 1:262792, z50mb_vec=67507*ones(i,1); end; toc;
tic; for i = 1:262792, z75mb_vec=60296*ones(i,1); end; toc;
% tic; for i = 1:262792, z100mb_vec=53084*ones(i,1); end; toc;
%
% tic; for i = 1:262792, z125mb_vec=48865*ones(i,1); end; toc;
%
% tic; for i = 1:262792, z150mb_vec=44646*ones(i,1); end; toc;
%
% tic; for i = 1:262792, z175mb_vec=43763*ones(i,1); end; toc;
%
% tic; for i = 1:262792, z200mb_vec=38661*ones(i,1); end; toc;
%
tic; for i = 1:262792, W_zerovec = 0*ones(i,1); end; toc;
%
% 3D quiver plots format: quiver3(x,y,z,u,v,w) -- Make sure dimensionality
% of all 6 components to that plot match up before plotting.
quiver3((lat_value(1:101)), (long_value(1:25)), ( z50mb_vec(1:25)), (UwindVec50mb(1:25)) ,(VwindVec50mb(1:25)) , W_zerovec(1:25))
hold on
quiver3((lat_value(1:101)), (long_value(1:251)), ( z75mb_vec(1:25)), (UwindVec75mb(1:25)) ,(VwindVec75mb(1:25)) , W_zerovec(1:25))
hold on
% quiver3((lat_value(1:101)), (long_value(1:101)), (z100mb_vec(1:101)), (UwindVec100mb(1:101)),(VwindVec100mb(1:101)), W_zerovec(1:101))
% hold on
% quiver3((lat_value(1:101)), (long_value(1:101)), (z125mb_vec(1:101)), (UwindVec125mb(1:101)),(VwindVec125mb(1:101)), W_zerovec(1:101))
% hold on
% quiver3((lat_value(1:101)), (long_value(1:101)), (z150mb_vec(1:101)), (UwindVec150mb(1:101)),(VwindVec150mb(1:101)), W_zerovec(1:101))
% hold on
% quiver3((lat_value(1:101)), (long_value(1:101)), (z175mb_vec(1:101)), (UwindVec175mb(1:101)),(VwindVec175mb(1:101)), W_zerovec(1:101))
% hold on
% quiver3((lat_value(1:101)), (long_value(1:101)), (z200mb_vec(1:101)), (UwindVec200mb(1:101)),(VwindVec200mb(1:101)), W_zerovec(1:101))
toc
A guy by the name of Failmond is provided me with this, which suitably solves my query! Thanks to all!
zLevels = 5; %number of interpolated points between z50 and z75
nStation = 100; %number of (lat,long) pairs to interpolate
for i = 1:nStation %for nStation different (lat, long) pairs generate interp. values
% generate zQuery points between z50 and z75 for each station
zQuery = ((1:zLevels)/zLevels)*range([z50mb_vec(i) z75mb_vec(i)]) + z75mb_vec(i);
% use interp1 to interpolate about the Z axis for U component
U(i,1:N) = interp1([z50mb_vec(i) z75mb_vec(i)],[UwindVec50mb(i) UwindVec75mb(i)],zQuery);
% and for V component
V(i,1:N) = interp1([z50mb_vec(i) z75mb_vec(i)],[VwindVec50mb(i) VwindVec75mb(i)],zQuery);
end
% defining some color codes for each zLevel, otherwise the plot is a mess
% of colors
colorcode = ['r' 'g' 'b' 'm' 'c' 'r' 'g' 'b' 'm' 'c' 'r'];
for j = 1:nStation
for i = 1:zLevels
quiver3(lat_value(j), long_value(j), zQuery(i), U(j,i), V(j,i), 0, colorcode(i));
hold on;
end
end
Hi I'm trying to calculate mfcc for which i'm windowing. I have seen this one post I'm getting error in fftOneSide.
my code is
waveFile='test_preEmphasis.wav';
[y, fs]=wavread(waveFile);
n=512;
t=(1:n)'/fs;
startIndex=30418;
endIndex=startIndex+n-1;
original=y(startIndex:endIndex);
windowed=original.*hamming(n);
[mag1, phase1, freq1]=fftOneSide(original, fs);
[mag2, phase2, freq2]=fftOneSide(windowed, fs);
subplot(3,2,1); plot(original); grid on; axis([-inf inf -1 1]);
title('Original signal');
subplot(3,2,2); plot(windowed); grid on; axis([-inf inf -1 1]);
title('Windowedsignal');
subplot(3,2,3); plot(freq1, mag1); grid on;
title('Energy spectrum (linear scale)');
subplot(3,2,4); plot(freq2, mag2); grid on;
title('Energy spectrum (linear scale)');
subplot(3,2,5); plot(freq1, 20*log(mag1)); grid on;
axis([-inf inf -80 120]); title('Energy spectrum (db)');
subplot(3,2,6); plot(freq2, 20*log(mag2)); grid on; axis([-inf inf -80 120]);
title('Energy spectrum (db)');
the error i'm getting is
??? Undefined function or method 'fftOneSide' for input arguments of type 'double'.
any help is appreciated
thanks
This is a really old post, it'd be neat if someone still cared. I just provided what I believe to be the answer in the recent post below, which I arrived at after a fair bit of frustration: Undefined function 'fftOneSide' for input arguments of type 'double'.
It should be noted here there's a call to a file, which I'm not sure if the author had originally or not. I suspect all the problems are related to a similarly named file in the sourcecode.
If you look at my discussion in the other post, within the function definition there is a call to a method demo with a file - which isn't present if you just have the function definition, not the original file. Calling [mag1, phase1, freq1]=fftOneSide(original, fs,1), after you comment out the first line if nargin <1... and the demo routine worked fine on my machine with the code which I'll show below. Having the third argument equal to 1 guarantees that the code will run the print routines, which is important.
In case the other thread is closed, I just want to show the output, when the input is manually defined, and I call [mag1, phase1, freq1]=fftOneSide(original, fs,1) on the properly edited method, with the inputs as in the original post shown below (notice the call is to original in fftOneSide..in the other post it was like this as well.. I believe the call was was meant to be instead for windowed, but I don't have the signals toolbox with hamming anyways):
fs=8000;
t=(1:512)'/fs; %'// <-- prevents string markdown
f=306.396;
original=sin(2*pi*f*t)+0.2*randn(length(t),1);
% windowed=original.*hamming(length(t)); % defined in other post
[mag1,phase1,freq1]=fftOneSide(original,fs); % I call fftOneSide(original,fs,1);
The output is as follows (source code below!)
Anyways, here's the source code in case anyone wants to use this function
function [magSpec, phaseSpec, freq, powerSpecInDb]=fftOneSide(signal, fs, plotOpt)
% fftOneSide: One-sided FFT for real signals
% Usage: [magSpec, phaseSpec, freq, powerSpecInDb]=fftOneSide(signal, fs)
%
% For example:
% [y, fs]=wavread('welcome.wav');
% frameSize=512;
% startIndex=2047;
% signal=y(startIndex:startIndex+frameSize+1);
% signal=signal.*hamming(length(signal));
% plotOpt=1;
% [magSpec, phaseSpec, freq, powerSpecInDb]=fftOneSide(signal, fs, plotOpt);
% Roger Jang, 20060411, 20070506
if nargin<1, selfdemo; return; end %=== (MathBio: Comment this out!)
if nargin<2, fs=1; end
if nargin<3, plotOpt=0; end
N = length(signal); % Signal length
freqStep = fs/N; % Frequency resolution
time = (0:N-1)/fs; % Time vector
z = fft(signal); % Spectrum
freq = freqStep*(0:N/2); % Frequency vector
z = z(1:length(freq)); % One side
z(2:end-1)=2*z(2:end-1); % Assuming N is even, symmetric data is multiplied by 2
magSpec=abs(z); % Magnitude spectrum
phaseSpec=unwrap(angle(z)); % Phase spectrum
powerSpecInDb=20*log(magSpec+realmin); % Power in db
if plotOpt
% ====== Plot time-domain signals
subplot(3,1,1);
plot(time, signal, '.-');
title(sprintf('Input signals (fs=%d)', fs));
xlabel('Time (seconds)'); ylabel('Amplitude'); axis tight
% ====== Plot spectral power
subplot(3,1,2);
plot(freq, powerSpecInDb, '.-'); grid on
title('Power spectrum');
xlabel('Frequency (Hz)'); ylabel('Power (db)'); axis tight
% ====== Plot phase
subplot(3,1,3);
plot(freq, phaseSpec, '.-'); grid on
title('Phase');
xlabel('Frequency (Hz)'); ylabel('Phase (Radian)'); axis tight
end
% ====== Self demo (MathBio: Comment all of this out! )
function selfdemo
[y, fs]=wavread('welcome.wav');
frameSize=512;
startIndex=2047;
signal=y(startIndex:startIndex+frameSize+1);
signal=signal.*hamming(length(signal));
[magSpec, phaseSpec, freq, powerSpecInDb]=feval(mfilename, signal, fs, 1);