* Bugs 10490 16530 fixed: mapsound fixed/reforged 72/21572/6
Samuel GOUGEON [Mon, 10 Aug 2020 12:21:52 +0000 (14:21 +0200)]
  http://bugzilla.scilab.org/16530
  http://bugzilla.scilab.org/10490

  mapsound page (PDF): http://bugzilla.scilab.org/attachment.cgi?id=5178

Change-Id: I72a260572a65ab761a844b77f5d5fbdd081d5c44

14 files changed:
scilab/CHANGES.md
scilab/modules/graphics/demos/technical/technical.dem.gateway.sce
scilab/modules/helptools/etc/images_md5.txt
scilab/modules/helptools/images/mapsound_1.png
scilab/modules/helptools/images/mapsound_2.png [new file with mode: 0644]
scilab/modules/helptools/images/mapsound_3.png [new file with mode: 0644]
scilab/modules/helptools/images/mapsound_4.png [new file with mode: 0644]
scilab/modules/helptools/images/mapsound_5.png [new file with mode: 0644]
scilab/modules/sound/demos/mapsound.dem.sce [new file with mode: 0644]
scilab/modules/sound/demos/sound.dem.gateway.sce
scilab/modules/sound/help/en_US/mapsound.xml
scilab/modules/sound/help/ja_JP/mapsound.xml [deleted file]
scilab/modules/sound/macros/mapsound.sci
scilab/modules/sound/tests/unit_tests/mapsound.tst

index 08f200e..3e17d34 100644 (file)
@@ -201,7 +201,6 @@ Feature changes and additions on 6.1.1
   - It can now sort any sparse 2D matrix, in all `g, r, c, lr, lc` methods, including sparse booleans and in multi-level mode. It was formerly limited to sparse real or complex vectors and only to the `g` mode.
   - Any hypermatrix can be sorted along a dimension > 2.
 * `unique` is enabled for any 2D sparse arrays, in simple, 'c' and 'r' modes.
-<<<<<<< HEAD
 * `%chars` constant added, to easily access to some selected sets of unicode symbols.
 * Lists are displayed in a more compact and comprehensive way.
 * `interp1` is upgraded:
@@ -215,9 +214,9 @@ Feature changes and additions on 6.1.1
   - bitnum can actually be an array. It is now optional as well for input decimal integers.
 * The `Arnoldi` module is now internal.
 * `sgolay` and the companion `sgolayfilter` and `sgolaydiff` functions have been added to implement Savitsky-Golay filters.
-=======
 * `clock` now returns the milliseconds, the time zone, and the daylight saving time.
->>>>>>> 6436aedaa9e (* Bug 16504 fixed: clock() upgraded (time zone, daylight ST))
+* `mapsound` upgraded to have a colormap argument
+
 
 Help pages:
 -----------
@@ -304,6 +303,7 @@ Bug Fixes
 * [#9909](https://bugzilla.scilab.org/9909): In the help browser, add a way to open the online version of the current page.
 * [#10046](https://bugzilla.scilab.org/10046): By default, the `MAXMIN` block did not propose 2 input ports to work in an element-wise way (unlike MIN_f and MAX_f), which is its most original working mode.
 * [#10476](https://bugzilla.scilab.org/10476): From `browsevar`, displaying the content of lists, structures, cells, or other custom tlists or mlists was not possible.
+* [#10490](https://bugzilla.scilab.org/10490): The `mapsound` page was poor with a single interesting example.
 * [#11677](https://bugzilla.scilab.org/11677): The original Arnoldi functions were obsolete.
 * [#12418](https://bugzilla.scilab.org/12418): Using bvode() with "continuation", i.e. `ipar(9) > 1` led to an error.
 * [#12516](https://bugzilla.scilab.org/12516): From `browsevar`, clicking on any graphical handle did not edit its figure with `ged`.
@@ -373,6 +373,7 @@ Bug Fixes
 * [#16517](https://bugzilla.scilab.org/16517): `getdate("s")` truncated the actual time to integer seconds. `getdate(u)(10)` returned fractional seconds instead of milliseconds as `getdate()`.
 * [#16522](https://bugzilla.scilab.org/16522): `bitget(x,pos)` and `bitset(x,pos)` results could be wrong when `pos` is an encoded integer.
 * [#16525](https://bugzilla.scilab.org/16525): `soundsec(t,freq)` has the trivial equivalence `0 : 1/freq : t*(1-%eps)` and should be removed.
+* [#16530](https://bugzilla.scilab.org/16530): `mapsound` needed to be reforged.
 * [#16549](https://bugzilla.scilab.org/16549): simple script crashed Scilab in GUI mode.
 * [#16551](https://bugzilla.scilab.org/16551): `num2cell` returned {} for any input array of empty strings.
 * [#16553](https://bugzilla.scilab.org/16553): `unique(["" ""])` returned `["" ""]`.
@@ -387,6 +388,7 @@ Bug Fixes
 * [#16654](https://bugzilla.scilab.org/16654): `interp` was leaking memory.
 
 
+
 ### Bugs fixed in 6.1.0:
 * [#2694](https://bugzilla.scilab.org/2694): `bitget` did not accept positive integers of types int8, int16 or int32.
 * [#5824](https://bugzilla.scilab.org/5824): The `datafit` algorithm was not documented.
index 764d409..16985f9 100644 (file)
@@ -16,6 +16,7 @@ subdemolist = [
 "Black-Nichols"      , "black.dem.sce"
 "s-grid"             , "sgrid.dem.sce"
 "z-grid"             , "zgrid.dem.sce"
+"mapsound"           , "../../../sound/demos/mapsound.dem.sce"
 ];
 
 subdemolist(:,2) = demopath + subdemolist(:,2);
index e7a0587..e5ced75 100644 (file)
@@ -845,7 +845,11 @@ lqg_1.png=3e8627090476b38335a391eb831767a6
 lqg_2.png=d0a7523f9ddee9c5f11c06682ff1b0c6
 lqr_1.png=269d7421a9d109d37259c9739612dd21
 lsq_splin_1.png=35722a6a58a3c9afd427b0bb23f1382a
-mapsound_1.png=a1d2da99607861bfe926b66b3fc145b2
+mapsound_1.png=775cb5d77a6f98c880e27960c4e39514
+mapsound_2.png=ea66eb5ccd62fd3d034df457c68d86ab
+mapsound_3.png=ae8b5e54d534fb6a64de9659665d5afa
+mapsound_4.png=572ed70b9c0491be98d7bc9a3c1cc83f
+mapsound_5.png=98d28e5f40d5579d1e6807aa87f31f9e
 math_rendering_features_in_graphic_1.png=b1259d51258d72193bd32a47c8f96ca4
 math_rendering_features_in_graphic_2.png=c93a1a79cbe217871185826f83fdd7bb
 mese_1.png=c4ce712eded4fbbd49bb86b02e14afe9
index 8309962..633ba6e 100644 (file)
Binary files a/scilab/modules/helptools/images/mapsound_1.png and b/scilab/modules/helptools/images/mapsound_1.png differ
diff --git a/scilab/modules/helptools/images/mapsound_2.png b/scilab/modules/helptools/images/mapsound_2.png
new file mode 100644 (file)
index 0000000..f7b5ad1
Binary files /dev/null and b/scilab/modules/helptools/images/mapsound_2.png differ
diff --git a/scilab/modules/helptools/images/mapsound_3.png b/scilab/modules/helptools/images/mapsound_3.png
new file mode 100644 (file)
index 0000000..83cbb2e
Binary files /dev/null and b/scilab/modules/helptools/images/mapsound_3.png differ
diff --git a/scilab/modules/helptools/images/mapsound_4.png b/scilab/modules/helptools/images/mapsound_4.png
new file mode 100644 (file)
index 0000000..afdcd9d
Binary files /dev/null and b/scilab/modules/helptools/images/mapsound_4.png differ
diff --git a/scilab/modules/helptools/images/mapsound_5.png b/scilab/modules/helptools/images/mapsound_5.png
new file mode 100644 (file)
index 0000000..ed0cc89
Binary files /dev/null and b/scilab/modules/helptools/images/mapsound_5.png differ
diff --git a/scilab/modules/sound/demos/mapsound.dem.sce b/scilab/modules/sound/demos/mapsound.dem.sce
new file mode 100644 (file)
index 0000000..2d5e36c
--- /dev/null
@@ -0,0 +1,104 @@
+// Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+// Copyright (C) 2020 - Samuel GOUGEON
+//
+// This file is hereby licensed under the terms of the GNU GPL v2.0,
+// pursuant to article 5.3.4 of the CeCILL v.2.1.
+// This file was originally licensed under the terms of the CeCILL v2.1,
+// and continues to be available under such terms.
+// For more information, see the COPYING file which you should have received
+// along with this program.
+
+function demo_mapsound()
+
+    idfig = 100001;
+
+    // Example #1: Standard
+    // ====================
+    fs = 22050;
+    t = 0:1/fs:1;
+    y = 0.3 + [1.5*sin(2*%pi*800*t) sin(2*%pi*1200*t)];
+    // Then: build and display its map:
+    fig = scf(idfig);
+    show_window(fig)
+    clf()  // reset
+    demo_viewCode("mapsound.dem.sce");
+    mapsound(y, 0.04, 1500)
+    title "0.3 + [1.5⋅sin(2π⋅800⋅t), sin(2π⋅1200⋅t)]" fontsize 3.2
+    // Let's hear it, not too loud:
+    playsnd(y/8)
+    msg = _(["<html><h4>Example #1: Standard</h4>" ;
+          "" ;
+          "A standard sound made of 2 pure sine waves" ;
+          "of known amplitudes and frequencies is considered." ;
+          "We add a constant on demo purpose. It should not be hearable." ;
+          "" ;
+          "<b>y = 0.3 + [1.5*sin(2*%pi*800*t) sin(2*%pi*1200*t)]</b>" ;
+          "playsnd(y/8)" ;
+          "<b>mapsound(y, 0.04, 1500)</b>" ;
+          "" ;
+          "Both main frequencies and amplitudes values are reliably mapped." ;
+          "The constant appears at the zero frequency and 2×0.3 expected amplitude"
+          ]);
+     go? = messagebox(msg, "mapsound","scilab",_(["Next example" ; "Stop"]), "modal");
+     if go?==2, close(fig), return, end
+
+
+    // Example #2: Wobbling
+    // ====================
+    fs = 22050; // Sampling frequency
+    t = 0:1/fs:1;
+    f = 500*(1-t) + 2000*t;
+    y0 = sin(2*%pi*f.*t);
+    y = [y0 y0 y0];
+    // Then: build and display its map:
+    fig = scf(idfig);
+    clf reset
+    mapsound(y)
+    title "Wobbling: y = sin(2π⋅f(t)⋅t), with f=500→2000→500 Hz" fontsize 3.5
+    demo_viewCode("mapsound.dem.sce");
+    // Let's hear it, not too loud:
+    playsnd(y/8)
+    //
+    msg = ["<html><h4>Example #2: Wobbling</h4>" ;
+          "" ;
+          "Here, the sound is a sine wave whose frequency varies linearly" ;
+          "in time on the [f0=550, f1=2000] Hz interval." ;
+          "This yields some actual higher frequencies, on [f0, 2*f1-f0]." ;
+          "We repeat it 3 times one second." ;
+          "" ;
+          "fs = 22050; // Sampling frequency" ;
+          "t = 0:1/fs:1;" ;
+          "<b>f = 500*(1-t) + 2000*t</b>; // Actual instantaneous frequency" ;
+          "<b>y0 = sin(2*%pi*f.*t)</b>;   // for one second" ;
+          "y = [y0 y0 y0];" ;
+          "" ;
+          "playsnd(y/8)" ;
+          "<b>mapsound(y)</b>" ;
+          ];
+     go? = messagebox(msg, "mapsound","scilab",_(["Next example" "Stop"]), "modal");
+     if go?==2, close(fig), return, end
+
+
+    // Example #3: Chimes
+    // ==================
+    [y, fs] = wavread('SCI/modules/sound/demos/chimes.wav');
+    fig = scf(idfig);
+    clf reset
+    mapsound(y,,2500,fs,parulacolormap)
+    title chimes.wav fontsize 3.5
+    demo_viewCode("mapsound.dem.sce");
+    playsnd(y)
+    msg = _(["<html><h4>Example #3: chimes.wav sound</h4>" ;
+          "" ;
+          "[y, fs] = wavread(""SCI/modules/sound/demos/chimes.wav"")";
+          "playsnd(y)" ;
+          "<b>mapsound(y, , 2500, fs, parulacolormap)</b>" ;
+          ]);
+     b = messagebox(msg, "mapsound","scilab", _(["End" ; "End & Keep the map"]), "modal");
+     if b==1, close(fig), end
+     // Otherwise: keeping the graphic figure allows to click on "View the code"
+
+endfunction
+
+demo_mapsound();
+clear demo_mapsound;
index 6b57ac1..29ebb2d 100644 (file)
@@ -9,11 +9,12 @@ function subdemolist = demo_gateway()
     gettext("Sound file handling");   // Lets gettext() harvesting it
     add_demo("Sound file handling", demopath + "sound.dem.gateway.sce");
 
-    subdemolist = [_("FFT on a wav file")  ,"sound.dem.sce"]
+    subdemolist = [_("FFT on a wav file")  , "sound.dem.sce"
+                     "mapsound"            , "mapsound.dem.sce"]
 
     subdemolist(:,2) = demopath + subdemolist(:,2);
 
 endfunction
 
 subdemolist = demo_gateway();
-clear demo_gateway;
\ No newline at end of file
+clear demo_gateway;
index 03c6f5d..a9eae29 100644 (file)
@@ -1,9 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
-    * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
-    * Copyright (C) ????-2006 - INRIA - Scilab
-    *
- * Copyright (C) 2012 - 2016 - Scilab Enterprises
+ * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
+ * Copyright (C) 2020 - Samuel GOUGEON
  *
  * This file is hereby licensed under the terms of the GNU GPL v2.0,
  * pursuant to article 5.3.4 of the CeCILL v.2.1.
           xmlns:scilab="http://www.scilab.org" xml:lang="en" xml:id="mapsound">
     <refnamediv>
         <refname>mapsound</refname>
-        <refpurpose>Plots a sound map</refpurpose>
+        <refpurpose>
+            Computes and displays an Amplitude(time, frequency) map of a sound record
+        </refpurpose>
     </refnamediv>
     <refsynopsisdiv>
         <title>Syntax</title>
-        <synopsis>mapsound (w,dt,fmin,fmax,simpl,rate)</synopsis>
+        <synopsis>
+            mapsound(signal)
+            mapsound(signal, Dt)
+            mapsound(signal, Dt, freqRange)
+            mapsound(signal, Dt, freqRange, samplingRate)
+            mapsound(signal, Dt, freqRange, samplingRate, Colormap)
+            [times, freqs, amplitudes] = mapsound(…)
+        </synopsis>
     </refsynopsisdiv>
     <refsection>
         <title>Arguments</title>
         <variablelist>
             <varlistentry>
-                <term>dt,fmin,fmax,simpl,rate</term>
+                <term>signal</term>
+                <listitem>
+                    Vector or matrix of signed real numbers representing the sound signal.
+                    If it's a matrix, its smallest size is considered as the number of channels.
+                    Then, only the first channel is considered and mapped.
+                    <para/>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>samplingRate</term>
+                <listitem>
+                    Positive decimal number: Value of the sampling rate of the input
+                    <varname>signal</varname>, in Hz. 22050 Hz is the default rate.
+                    <para/>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>freqRange</term>
+                <listitem>
+                    Specifies the interval [fmin, fmax] of positive sound frequencies to be
+                    analyzed and mapped:
+                    <itemizedlist>
+                        <listitem>
+                            If it's a scalar: It specifies the upper bound <varname>fmax</varname>.
+                            Then <literal>fmin=0</literal> is used.
+                        </listitem>
+                        <listitem>
+                            If it's a vector: It specifies [fmin, fmax].
+                        </listitem>
+                    </itemizedlist>
+                    If a bound is > 0, it is specified in Hz. If it's negative, its absolute value
+                    represents a fraction of the sampling rate. For instance, fmax=-0.2 actually
+                    specifies fmax = 0.2 * samplingRate.
+                    <para/>
+                    The default bounds are <literal>[0, 0.2*samplingRate]</literal>.
+                    <para/>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>Dt</term>
+                <listitem>
+                    Specifies the time step of the map. The time step is also the
+                    duration of each sound chunk considered at every time step, since the
+                    <varname>signal</varname> is sliced into contiguous chunks without overlap.
+                    <para/>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>times</term>
                 <listitem>
-                    <para>scalars. default values dt=0.1,fmin=100,fmax=1500,simpl=1,rate=22050;</para>
+                    Vector of mapped times, in seconds.
+                    <para/>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>freqs</term>
+                <listitem>
+                    Vector of mapped frequencies, in Hz.
+                    <para/>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>amplitudes</term>
+                <listitem>
+                    Matrix of mapped absolute spectral amplitudes, of size length(freqs)×length(times).
+                    <para/>
+                </listitem>
+            </varlistentry>
+            <varlistentry>
+                <term>Colormap</term>
+                <listitem>
+                    Identifier of the colormap function to use: autumncolormap, bonecolormap, etc.
+                    The actual colormap is based on and built with it, but is not equal to it.
+                    It can be inverted in order to get light colors for low amplitudes,
+                    and be extrapolated to white if it does not natively include light colors.
+                    <para/>
                 </listitem>
             </varlistentry>
         </variablelist>
     <refsection>
         <title>Description</title>
         <para>
-            Plots a sound map for a sound. It does FFT at time increments dt.
-            <literal>rate</literal> is the sampling rate. <literal>simpl</literal> points are collected for
-            speed reasons. <literal>fmin</literal> and <literal>fmax</literal> are used for graphic
-            boundaries.
+            mapsound(…) slices the input signal in consecutive chunks #0, #1,.. of equal duration
+            <varname>Dt</varname>, up to the end of the signal. Then a discrete Fourier Transform
+            is computed for each chunk. The absolute value of the spectral amplitude of the chunk
+            #i is displayed at the time i*Dt, for frequencies in the chosen interval.
+        </para>
+        <para>
+            When <varname>Dt</varname> is not specified, mapsound(…) computes it in order to have
+            (almost) the same number of frequency and time bins, with the highest possible
+            (time, frequency) resolution. We may keep in mind that both time <varname>Dt</varname>
+            and frequency Δf steps are linked together by <literal>Dt.Δf=1</literal>. Thus, improving
+            one of both automatically alters the other one.
+        </para>
+        <para>
+            The (time, frequency, amplitude) values of any pixel are relative to its lower left
+            corner. The time is at the beginning of the chunk. Amplitudes are given in the
+            same unit and scale than for the input signal.
+        </para>
+        <para>
+            When the map is drawn in a new figure or a new axes alone in the figure,
+            a smart colormap is created and assigned to the figure and used for the map.
+            A colobar is displayed anyway. The number of frequency and time bins are
+            displayed below the bar. The default grid color is extracted from the sound map
+            colormap. <literal>xgrid(0)</literal> may be used to get a more visible black grid.
+        </para>
+        <para>
+            Most of input arguments are optional. To skip an argument and use its default value,
+            just omit it before the next coma. [] used as default value works as well.
         </para>
     </refsection>
     <refsection>
         <title>Examples</title>
+        <para>
+            <emphasis role="bold">Example #1:</emphasis> A sound made of 2 pure sine waves of
+            known amplitudes and frequencies is considered:
+        </para>
         <programlisting role="example"><![CDATA[
-// At first we create a time vector of 0.5 seconds sampled at 22050 Hz:
-t = 0 : 1/22050 : 0.5*(1-%eps);
+// Let's build the sound
+// 1 s at 800 Hz @ amplitude=1.5, then 1 s at 1200 Hz @ amplitude = 1:
+fs = 22050;
+t = 0:1/fs:1*(1-%eps);
+y = 0.3 + [1.5*sin(2*%pi*800*t) sin(2*%pi*1200*t)];
 
-// Then we generate the sound.
-s=sin(440*t)+sin(220*t)/2+sin(880*t)/2;
-[nr,nc]=size(t);
-s(nc/2:nc)=sin(330*t(nc/2:nc));
-mapsound(s);
- ]]></programlisting>
+// Let's hear it:
+playsnd(y/4)
+
+// Then: build and display its map:
+clf
+mapsound(y, 0.04, 1500)
+title "0.3 + [1.5⋅sin(2π⋅800⋅t), sin(2π⋅1200⋅t)]" fontsize 3.2
+      ]]></programlisting>
+        <scilab:image>
+            fs = 22050;
+            t = (0:fs-1)/fs;
+            y = 0.3 + [1.5*sin(2*%pi*800*t) sin(2*%pi*1200*t)];
+            mapsound(y, 0.04, 1500)
+            title "0.3 + [1.5⋅sin(2π⋅800⋅t), sin(2π⋅1200⋅t)]" fontsize 3.2
+        </scilab:image>
+        <para>
+            Both frequencies and amplitudes values are reliably mapped, as well as the
+            average level, with the 2×0.3 amplitude at the zero frequency.
+        </para>
+        <para>
+            <emphasis role="bold">Example #2:</emphasis> Amplitude modulation: A Fc=1000 Hz
+            carrier frequency is used, modulated in a Fm=100 Hz envelope.
+        </para>
+        <programlisting role="example"><![CDATA[
+fs = 22050;
+t = (0:2*fs-1)/fs;
+y = sin(2*%pi*100*t) .* sin(2*%pi*1000*t);
+
+// Let's hear it:
+playsnd(y/4)
+
+// Then: build and display its map:
+clf
+mapsound(y, 0.05, [500 1300])
+title "sin(2π⋅100⋅t) ⋅ sin(2π⋅1000⋅t)" fontsize 3.2
+      ]]></programlisting>
+        <scilab:image>
+            fs = 22050;
+            t = (0:2*fs-1)/fs;
+            y = sin(2*%pi*100*t) .* sin(2*%pi*1000*t);
+            mapsound(y, 0.05, [500 1300])
+            title "sin(2π⋅100⋅t) ⋅ sin(2π⋅1000⋅t)" fontsize 3.2
+        </scilab:image>
+        <para>
+            As a consequence of the <literal>sin(a).sin(b)=(cos(a-b)-cos(a+b))/2</literal> formula,
+            both resulting frequencies [Fc-Fm, Fc+Fm] expected from the amplitude
+            modulation are clearly visible, with a shared amplitude=0.5
+        </para>
+
+        <para>
+            <emphasis role="bold">Example #3:</emphasis> Wobbling. Here, the frequency of a
+            sine wave is linearly varied on [f0, f1]. This yields some actual higher frequencies,
+            on [f0, 2*f1-f0]:
+        </para>
+        <programlisting role="example"><![CDATA[
+fs = 22050;
+t = (0:fs-1)/fs;
+f = 500*(1-t) + 2000*t;
+y0 = sin(2*%pi*f.*t);
+y = [y0 y0($:-1:1)];
+
+playsnd(y/4)
+
+clf
+mapsound(y)
+title "Wobbling: y = sin(2π⋅f(t)⋅t), with f=500→2000→500 Hz" fontsize 3.5
+      ]]></programlisting>
+        <scilab:image>
+            fs = 22050;
+            t = (0:fs-1)/fs;
+            f = 500*(1-t) + 2000*t;
+            y0 = sin(2*%pi*f.*t);
+            y = [y0 y0($:-1:1)];
+            mapsound(y)
+            title "Wobbling: y = sin(2π⋅f(t)⋅t), with f=500→2000→500 Hz" fontsize 3.5
+        </scilab:image>
+
+        <para>
+            <emphasis role="bold">Example #4:</emphasis> Chimes.wav : a quite structured sound
+        </para>
+        <programlisting role="example"><![CDATA[
+[s1, fs1] = wavread('SCI/modules/sound/demos/chimes.wav');
+
+playsnd([]), sleep(500), playsnd(s1/2), sleep(1000)
+
+clf
+mapsound(s1,, 2300, , parulacolormap)
+title Chimes.wav fontsize 3.5
+      ]]></programlisting>
         <scilab:image>
-            t = 0 : 1/22050 : 0.5*(1-%eps);
-            s=sin(440*t)+sin(220*t)/2+sin(880*t)/2;
-            [nr,nc]=size(t);
-            s(nc/2:nc)=sin(330*t(nc/2:nc));
-            mapsound(s);
+            [s1, fs1] = wavread('SCI/modules/sound/demos/chimes.wav');
+            clf
+            mapsound(s1,,2300,,parulacolormap)
+            title Chimes.wav fontsize 3.5
         </scilab:image>
+
+        <para>
+            <emphasis role="bold">Example #5:</emphasis> Another sound, longer and more noisy
+        </para>
+        <programlisting role="example"><![CDATA[
+[s2, fs2] = wavread('SCI/modules/sound/tests/nonreg_tests/bug_467.wav');
+
+playsnd([]), sleep(500), playsnd(s2/3)
+
+clf
+mapsound(s2, , 4000)
+title Din fontsize 3.5
+      ]]></programlisting>
+        <scilab:image>
+            [s2, fs2] = wavread('SCI/modules/sound/tests/nonreg_tests/bug_467.wav');
+            mapsound(s2, , 4000)
+            title Din fontsize 3.5
+        </scilab:image>
+    </refsection>
+    <refsection role="see also">
+        <title>See also</title>
+        <simplelist type="inline">
+            <member>
+                <link linkend="fft">fft</link>
+            </member>
+            <member>
+                <link linkend="analyze">analyze</link>
+            </member>
+            <member>
+                <link linkend="intdec">intdec</link>
+            </member>
+        </simplelist>
+    </refsection>
+    <refsection role="history">
+        <title>History</title>
+        <revhistory>
+            <revision>
+                <revnumber>6.1.1</revnumber>
+                <revdescription>
+                    mapsound() rewritten: fmin and fmax merged into freqRange ;
+                    Colormap, times, frequencies, amplitudes arguments added ;
+                    simpl removed.
+                </revdescription>
+            </revision>
+        </revhistory>
     </refsection>
 </refentry>
diff --git a/scilab/modules/sound/help/ja_JP/mapsound.xml b/scilab/modules/sound/help/ja_JP/mapsound.xml
deleted file mode 100644 (file)
index 1507126..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
-    * Copyright (C) ????-2006 - INRIA - Scilab
-    *
- * Copyright (C) 2012 - 2016 - Scilab Enterprises
- *
- * This file is hereby licensed under the terms of the GNU GPL v2.0,
- * pursuant to article 5.3.4 of the CeCILL v.2.1.
- * This file was originally licensed under the terms of the CeCILL v2.1,
- * and continues to be available under such terms.
- * For more information, see the COPYING file which you should have received
- * along with this program.
-    *
-    -->
-<refentry xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svg="http://www.w3.org/2000/svg" xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:db="http://docbook.org/ns/docbook" xmlns:scilab="http://www.scilab.org" xml:lang="ja" xml:id="mapsound">
-    <refnamediv>
-        <refname>mapsound</refname>
-        <refpurpose>サウンドマップをプロット</refpurpose>
-    </refnamediv>
-    <refsynopsisdiv>
-        <title>呼び出し手順</title>
-        <synopsis>mapsound (w,dt,fmin,fmax,simpl,rate)</synopsis>
-    </refsynopsisdiv>
-    <refsection>
-        <title>引数</title>
-        <variablelist>
-            <varlistentry>
-                <term>dt,fmin,fmax,simpl,rate</term>
-                <listitem>
-                    <para>スカラー. デフォルト値 dt=0.1,fmin=100,fmax=1500,simpl=1,rate=22050;</para>
-                </listitem>
-            </varlistentry>
-        </variablelist>
-    </refsection>
-    <refsection>
-        <title>説明</title>
-        <para>
-            音のサウンドマップをプロット. 時間増分dt毎にFFTを行います.
-            <literal>rate</literal> はサンプリング・レートです.
-            速度面を考慮して<literal>simpl</literal> 点が収集されます.
-            <literal>fmin</literal> および <literal>fmax</literal> が
-            グラフィック境界として使用されます.
-        </para>
-    </refsection>
-    <refsection>
-        <title>例</title>
-        <programlisting role="example"><![CDATA[
-// まず0.5秒分のサウンドパラメータを生成
-t = 0 : 1/22050 : 0.5*(1-%eps);
-
-// 次にサウンドを生成.
-s=sin(440*t)+sin(220*t)/2+sin(880*t)/2;
-[nr,nc]=size(t);
-s(nc/2:nc)=sin(330*t(nc/2:nc));
-mapsound(s);
- ]]></programlisting>
-        <scilab:image>
-            t = 0 : 1/22050 : 0.5*(1-%eps);
-            s=sin(440*t)+sin(220*t)/2+sin(880*t)/2;
-            [nr,nc]=size(t);
-            s(nc/2:nc)=sin(330*t(nc/2:nc));
-            mapsound(s);
-        </scilab:image>
-    </refsection>
-</refentry>
index 91c86f0..d2812be 100644 (file)
@@ -1,7 +1,5 @@
 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
-// Copyright (C) ???? - INRIA - Scilab
-//
-// Copyright (C) 2012 - 2016 - Scilab Enterprises
+// Copyright (C) 2020 - Samuel GOUGEON
 //
 // This file is hereby licensed under the terms of the GNU GPL v2.0,
 // pursuant to article 5.3.4 of the CeCILL v.2.1.
 // For more information, see the COPYING file which you should have received
 // along with this program.
 
-function mapsound (w,dt,fmin,fmax,simpl,rate)
-    // Plots a sound map for a sound.
-    // It does FFT at time increments dt.
-    // rate is the sampling rate.
-    // simpl points are collected for speed reasons.
-
-    [lhs,rhs]=argn(0);
-    if ( rhs <= 5 ) then rate=0;end
-    if ( rhs <= 4 ) then simpl=1; end ;
-    if ( rhs <= 3 ) then fmax=1500; end ;
-    if ( rhs <= 2 ) then fmin=100; end ;
-    if ( rhs <= 1 ) then dt=0.1;  end ;
-    n=prod(size(w));
-    defaultrate=22050;
-    if rate==0; rate=defaultrate; end;
-    dp=dt*rate;
-    points=2^floor(log(dp)/log(2));
-    ind=fmin/rate*points/simpl:fmax/rate*points/simpl;
-    f=abs(fft(w(1:points),1));
-    f=sum(matrix(f,points/simpl,simpl),"c")';
-    M=f(ind);
-    i=1;
-    i=i+dp;
-    while i+points <= n;
-        f=abs(fft(w(i:i+points-1),1));
-        f=sum(matrix(f,points/simpl,simpl),"c")';
-        M=[M;f(ind)];
-        i=i+dp;
-    end;
-    [nl,nc]=size(M);
-    if nl==1 ; return;end
-    x_abs= (0:(nl-1))*(n/rate)/(nl-1);
-    y_abs= (0:(nc-1))/(nc-1);
-    y_abs= fmin*(1-y_abs) + fmax*(y_abs)
-    grayplot(x_abs,y_abs,-M)
+function varargout = mapsound(w, dt, frange, rate, Colormap)
+    // rate: Sampling rate [Hz]
+    // frange = fmax (with fmin=0) | [fmin fmax]
+    // varargout = list(dates_vector, frequencies_vector, amplitudes_matrix)
+    if ~isdef("rate","l") | rate==[] then
+        rate = 22050
+    end
+    nSamples = max(size(w))
+    T = nSamples / rate
+
+    if ~isdef("frange","l") | frange==[] then
+        fmin = 0
+        fmax = -0.2     // Could be set according to an amplitude threshold
+    elseif length(frange)==1
+        fmin = 0
+        fmax = frange
+    else
+        [fmin, fmax]= (frange(1), frange(2))
+    end
+    if fmin < 0
+        fmin = rate * abs(fmin)
+    end
+    if fmax < 0 & abs(fmax) < 1
+        fmax = rate * abs(fmax)
+    end
+
+    if ~isdef("dt","l") | dt==[] then
+        nspect = floor(sqrt(fmax*T))    // => nspect =~= nfreq
+        dt = T / nspect
+    elseif dt < 0   // -dt indicates the wished number of spectra
+        dt = abs(dt) * T
+        nspect = floor(T / dt)
+    else
+        nspect = floor(T / dt)
+    end
+    if ~isdef("fmin","l") then
+        fmin = 0
+    end
+    //
+    dp = round(dt*rate)
+    [x, y] = ndgrid(1:dp, 0:(nspect-1))
+    ind = x + floor(y * dt * rate);
+
+    M = abs(fft(w(ind), -1, 1))
+    M = M(1:ceil(dp/2), :) // spectra are even, since the input signal is real
+
+    df = 1 / (dp/rate);
+    frequencies = (0:(dp-ceil(dp/2))) * df
+    sel = find(frequencies >= fmin & frequencies <= fmax)
+    M = M(sel,:) / length(frequencies)
+    frequencies = frequencies(sel)
+    dates = (0:size(M,2)-1) * dt
+
+    // Display
+    // -------
+    // Set a smart colormap if it is not disturbing:
+    gridColor = 0 // default value = black
+    // menus are not clf reset and must not prevent initializing the colormap:
+    if winsid() <> [] then
+        tmp = gca().parent.children.type
+        tmp(tmp=="uimenu") = []
+    end
+    if isdef("Colormap","l") | winsid()==[] | (size(tmp,"*")==1 & ..
+        size(gcf().color_map,1)==size(gdf().color_map,1) & ..
+        length(gca().children)==0) then
+        e = 0 // extension of the raw colormap to white (number of graded colors)
+              // e < 0 => invert the order the native colormap part
+              //          in order to get lighter colors for lower amplitudes
+        if isdef("Colormap","l") then
+            select Colormap
+            case autumncolormap, e = -15
+            case bonecolormap, e = -1
+            case coolcolormap, e = 20
+            case coppercolormap, e = -15
+            case graycolormap, e = -1
+            case hotcolormap, e = -1
+            case hsvcolormap, e = 15
+            case jetcolormap, e = -20
+            case oceancolormap, e = -1
+            case parulacolormap, e = -10,
+            case pinkcolormap, e = -1
+            case rainbowcolormap, e = 20
+            case springcolormap, e = -10
+            case summercolormap, e = -10
+            case wintercolormap, e = -20
+            else
+                if type(Colormap)<>13
+                    msg = _("%s: Argument #%d: Function expected.\n")
+                    error(msprintf(msg, "mapsound", 5))
+                end
+                msg = _("%s: Argument #%d: A colormap function expected.\n")
+                error(msprintf(msg, "mapsound", 5))
+            end
+            tmp = Colormap(100 - abs(e))
+            if e < 0  then
+                tmp = tmp($:-1:1,:)
+                e = abs(e)
+            end
+            if e then
+                tmp = [ones(e,3) - linspace(0, 1-1/e, e)'*([1 1 1] - tmp(1,:)); tmp]
+            end
+            // grid: color closest to grey50
+            [?,k] = gsort(sum((ones(tmp)*0.5 - tmp).^2,"c"),"g","i")
+            gridColor = k(find(k>e,1))
+        else
+            tmp = hotcolormap(118)($:-1:$*0.15,:);
+            gridColor = 43
+        end
+        gcf().color_map = tmp;
+    end
+
+    // Graphical preparation
+    ax = gca();
+    ax.tight_limits = "on";
+    ax.grid_position = "foreground"
+    xlabel(_("Time [s]"), "fontsize",2)
+    ylabel(_("Frequency [Hz]"), "fontsize",2)
+
+    // Display the map
+    //surf(dates, frequencies-(frequencies(2)-frequencies(1))/2, M)
+    surf(dates, frequencies, M)
+    ax.view = "2d";
+    gce().color_mode = -2
+    xgrid(gridColor)
+
+    colorbar
+    title(gce(), _("Amplitude"))
+    xlabel(msprintf("%d × %d",size(M)), "fontsize",2)
+    set("current_entity", ax.children)
+    sca(ax)
+
+    // Results
+    lhs = argn(1)
+    varargout = list()
+    if lhs > 0 then
+        varargout = list(dates)
+    end
+    if lhs > 1 then
+        varargout($+1) = frequencies
+    end
+    if lhs > 2 then
+        varargout($+1) = M
+    end
 endfunction
index 952246d..c4f3550 100644 (file)
-// =============================================================================
 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
-// Copyright (C) ????-2008 - INRIA
+// Copyright (C) 2020 - Samuel GOUGEON
 //
-//  This file is distributed under the same license as the Scilab package.
-// =============================================================================
+// This file is hereby licensed under the terms of the GNU GPL v2.0,
+// pursuant to article 5.3.4 of the CeCILL v.2.1.
+// This file was originally licensed under the terms of the CeCILL v2.1,
+// and continues to be available under such terms.
+// For more information, see the COPYING file which you should have received
+// along with this program.
+// ============================================================================
 //
 // <-- NO CHECK REF -->
+// <-- TEST WITH GRAPHIC -->
+//
+// Unitary test or mapsound()
+// ==========================
+
+fs = 22050;
+t = 0:1/fs:1*(1-%eps);
+y = 0.3 + [1.5*sin(2*%pi*800*t) sin(2*%pi*1200*t)];
+
+// All default arguments
+// ---------------------
+clf reset
+mapsound(y)
+ax = gca();
+assert_checkalmostequal(ax.x_ticks.locations, (0:0.2:1.8)', 2*%eps);
+assert_checkequal(ax.y_ticks.locations, (0:500:4000)');
+assert_checkequal(ax.children.type, "Fac3d");
+assert_checkequal(ax.grid_position, "foreground");
+
+smap = ax.children;
+assert_checkequal(smap.type, "Fac3d");
+assert_checkequal(smap.data_mapping, "scaled");
+assert_checkequal(smap.color_flag, 4);
+
+assert_checkequal(ax.x_label.text, _("Time [s]"));
+ref = linspace(0, 1.956989247, 92);
+assert_checkalmostequal(smap.data.x(1,1:92), ref);
+
+assert_checkequal(ax.y_label.text, _("Frequency [Hz]"));
+ref = linspace(0, 4326.265823, 94);
+assert_checkalmostequal(smap.data.y(1,1:92:$), ref);
+
+cb = gcf().children(1);
+assert_checkequal(cb.title.text, _("Amplitude"));
+assert_checkequal(cb.x_label.text, "95 × 93");
+assert_checkalmostequal(cb.y_ticks.locations, (0:0.2:1.4)', 2*%eps);
+assert_checkequal(size(gcf().color_map,1), 101);
+
+
+// Setting Dt
+// ----------
+Dt = 0.04;
+clf
+[t, f] = mapsound(y, Dt);
+assert_checkequal([t(2) f(2)], [Dt 25]);
+
+clf
+[t, f] = mapsound(y, -1/20);
+assert_checkequal([t(2) f(2)], [0.1 10]);
+
+
+// Setting displayed frequencies
+// -----------------------------
+clf
+[t, f] = mapsound(y, , 1300);
+assert_checkequal([t(2), f(1), f(2), f($)], [0.04 0 25 1300]);
+
+clf
+[t, f] = mapsound(y, , [500 1300]);
+assert_checkequal([t(2), f(1), f(2)-f(1), f($)], [0.04 500 25 1300]);
+
+[t, f] = mapsound(y, , -1/11);
+assert_checkequal([f(1), f(2), f($)], [0, 31.5, 1984.5]);
+assert_checkalmostequal(t(2), 0.031746032);
+
+clf
+[t, f] = mapsound(y, , [500 -1/11]);
+assert_checkequal([f(1), f(2)-f(1), f($)], [504, 31.5, 1984.5]);
+assert_checkalmostequal([t(2) t($)], [0.031746032 1.968253968]);
+
+clf
+[t, f] = mapsound(y, , [-1/110 -1/11]);
+assert_checkequal([f(1), f(2)-f(1), f($)], [220.5, 31.5, 1984.5]);
+assert_checkalmostequal([t(2) t($)], [0.031746032 1.968253968]);
+
+
+// With Colormap
+// -------------
+clf
+mapsound(y, 0.04, , , parulacolormap)
+ref = [1       1       1
+       0.99052 0.99324 0.62152
+       0.9763  0.9831  0.0538
+       0.2081  0.1663  0.5292];
+assert_checkequal(gcf().color_map([1 5 11 $],:), ref);
 
-// At first we create a time vector of 0.5 seconds sampled at 22050 Hz:
-t = 0 : 1/22050 : 0.5*(1-%eps);
+msg = msprintf(_("%s: Argument #%d: A colormap function expected.\n"), "mapsound", 5);
+assert_checkerror("mapsound(y, 0.04, , , members)", msg);
 
-// Then we generate the sound.
-s=sin(440*t)+sin(220*t)/2+sin(880*t)/2;
-[nr,nc]=size(t);
-s(nc/2:nc)=sin(330*t(nc/2:nc));
-mapsound(s);
+msg = msprintf(_("%s: Argument #%d: Function expected.\n"), "mapsound", 5);
+assert_checkerror("mapsound(y, 0.04, , , sin)", msg);