2
$\begingroup$

How can the v9.0 built-in Spectrogram[list, n, d] function be modified to accept complex exponential functions?

The V8.0.4 code that produces the result I'm looking for follows. How do I adapt v9.0 to do the same thing?

*************
(* Spectrogram of complex exponentials using MMA_ 8.0.4 *)
Clear[se, \
fs, \[CapitalDelta]T, n]; se[amp_, f_] := amp*Exp[2 \[Pi] I f t]
fs = 100 ; \[CapitalDelta]T = 130 ; \[CapitalDelta]t = N[1/fs]; n = 
 fs*\[CapitalDelta]T; \[CapitalDelta]f = 
 N[1/(2 \[CapitalDelta]T)] ; fmax = N[1/(2 \[CapitalDelta]t)];
Clear[f1, f2, f3]; f1 = 10; f2 = 20; f3 = -13; 
cs1 = N[Table[
   se[1, f1] , {t, 0, \[CapitalDelta]T, \[CapitalDelta]t}] ]; cs1 = 
 Most[cs1];
cs2 = N[Table[
   se[1, f2] , {t, 0, \[CapitalDelta]T, \[CapitalDelta]t}] ]; cs2 = 
 Most[cs2];
cs3 = N[Table[
   se[1, f3] , {t, 0, \[CapitalDelta]T, \[CapitalDelta]t}] ]; cs3 = 
 Most[cs3];
w1 = Table[
  1, {4000}];  Length[w1]; (* rectangular window *)
Length[cs1] ;
w1ls = ArrayPad[w1, {0, Length[cs1] - Length[w1]} ]; Length[w1ls] ;
wcs1 = w1ls*cs1; Length[wcs1];
ListLinePlot[Re[wcs1], Frame -> True, PlotRange -> All, 
  PlotStyle -> Blue, ImageSize -> 250];
w2 = Table[1, {4000}]; Length[w2];
Length[cs2];
w2ls = ArrayPad[
  w2, {Length[w1] + 1 , ( 
    Length[cs2] - Length[w1] - 1 - Length[w2])  }]; Length[w2ls];
wcs2 = w2ls*cs2; Length[wcs2];
ListLinePlot[Re[wcs2], Frame -> True, PlotRange -> All, 
  PlotStyle -> Green, ImageSize -> 250];
w3 = Table[1, {5000}]; Length[w3];
Length[cs3] ;
w3ls = ArrayPad[
  w3, { (Length[w1] + 1 + Length[w2] + 1), ( 
    Length[cs3] - Length[w1] - Length[w2] - 1 - Length[w3] - 
     1 )}];  Length[w3ls];
wcs3 = w3ls*cs3; Length[wcs3];
(********)
Clear[in]; in = 
 wcs1 + wcs2 + 
  wcs3 ;(* Composite Complex Signal *)
(********)
(* Set up STFT \
parameters *)
ns = 100 ;(*specify # samples/segment*)
insegs = 
 Partition[in, ns, 1, {1, 1}];
finsegs = 
  Chop[Fourier[#, FourierParameters -> {-1, -1}] ] & /@ insegs; 
ffinsegs = Abs[finsegs]^2;
rffinsegs = RotateRight[#, (ns/2) - 1] & /@ ffinsegs; 
p = ArrayPlot[Transpose[rffinsegs], DataReversed -> True,
  FrameTicks -> 
   {   { { { 
       0, - 5*fmax/5}, {ns*(1/10), -4*fmax/5}, {ns*(2/10), -3*fmax/5},
       {ns*(3/10), -2*fmax/5}, {ns*(4/10), -1*fmax/5},
      {ns*(5/10), 0}, {ns*(6/10), fmax/5}, {ns*(7/10), 
       2*fmax/5}, {ns*(8/10), 3*fmax/5 }, {ns*(9/10), 
       4*fmax/5}, {ns*(10/10), 5*fmax/5 "Hz"} }, None } ,
      { {{1000, 10}, {2000, 20}, {3000, 30}, {4000, 40}, {5000, 
       50}, {6000, 60}, {7000, 70}, {8000, 80}, {9000, 90}, {10000, 
       100}, {11000, 110}, {12000, 120}, {13000, 130 "sec"} }, 
     None }  },
   AspectRatio -> 1/3 , ImageSize -> 650 , 
  BaseStyle -> {FontFamily -> "Arial", FontWeight -> Bold, 12}]

(* MMA_ 9.0: Using built-in command < Spectrogram[list,n,d] > *)

Spectrogram[in, 100, 1]
Spectrogram[Re[in], 100, 1]
$\endgroup$

1 Answer 1

4
$\begingroup$

Could you try this?

Unprotect[Evaluate@Spectrogram];
PrependTo[DownValues@Spectrogram, 
  HoldPattern@
    Spectrogram[l : {___, _Complex, ___}, 
     n : (_Integer | Automatic) : Automatic, 
     m : (_Integer | Automatic) : Automatic, OptionsPattern[]] :> 
   Spectrogram[Re@InverseFourier@PadRight[Fourier@l, 2 Length@l, 0`], 
    If[n === Automatic, ## &[], 2 n], 
    If[m === Automatic, ## &[], 2 m], 
    SampleRate :> 
     If[OptionValue[SampleRate] === Automatic, Automatic, 
      2 OptionValue[SampleRate]]]];
Protect[Spectrogram];

So if

Spectrogram[Table[Cos[ i/4 + (i/20)^2], {i, 2000}], SampleRate -> 10]

gives

Mathematica graphics

then

Spectrogram[Table[Cos[ i/4 + (i/20)^2], {i, 2000}] + 0.01 I, 
 SampleRate -> 10]

gives

Mathematica graphics

$\endgroup$
3
  • $\begingroup$ I honestly couldn't test it much or try your code but I figure you want it to work like Matlab's, where if complex, the full spectrum is shown. I'll be back in some minutes and delete this if it doesn't work as intended $\endgroup$
    – Rojo
    Commented Feb 4, 2013 at 9:35
  • $\begingroup$ Thanks for the hint. I find that using your mod results in a disparity between the window size (that seems to be locked at 2) and the desired partition size, 100 in my case. Any ideas? $\endgroup$
    – stqnt
    Commented Feb 6, 2013 at 16:00
  • $\begingroup$ Oh, yeah, sorry about that @stqnt. I double the points so probably n and d should be doubled too? Check it, I'll edit now $\endgroup$
    – Rojo
    Commented Feb 6, 2013 at 19:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.