
Instructions for the utility programs  "Sound Input"  und  "Sound Output"
==========================================================================

  File: soundutl\SoundUtilityInfo_01.txt
  Author:  Wolfgang Buescher (DL4YHF)
  Revision Date: 2022-10-17 (ISO-8601 format: YYYY-MM-DD)


This is just a preliminary description of the tools to read samples
from a soundcard (etc) into a continuous "file stream" and vice versa.

For a start, here the description of the "SndInput" utility which
reads analog samples from the soundcard (A/D-converter).

The program shall read a continuous stream of samples from the ADC,
and put them in small "chunks" as temporary files to any other program
which processes the audio data.

The "Sound Input Utility" (SndInput.exe) will be called "producer"
in the following, the program which processes the audio data further
will be called "consumer".

The "Sound Output Utility" (SndOutpt.exe) works the other way round,
it "eats up" audio files and sends the samples to the D/A-converter
of the soundcard.

Other tools like "SerInput" work almost the same way, but they receive
samples from other sources (like an external hardware connected to the
PC's serial port, "COM1" or "COM2"). The firmware for such a converter
using a cheap PIC microcontroller is available on the author's homepage.

  These utilities were originally written in Borland C++Builder V4,
  but most of them can also be compiled with Dev-C++ since 2006-07.
  Sourcecode are available from the author for non-commercial purposes.


Principle (SndInput=Producer)
--------------------------------------------------------------------------

1.)  Producer acquires audio samples in a RAM buffer
     [ under windows: in a high-priority Thread, so nothing gets lost ].

2.)  Whenever possible, the producer writes as many samples as possible
     from the RAM buffer into a temporary(!) file.

3.)  As soon as the producer notices the "audio transport file"
     does not exist (because the "consumer" has eaten it),
     the producer renames the temporary file,
     for example from "audio.tmp" into "audio.dat".
     [ this happens in a single Win32-API-call, to avoid inconsistence.
       In the moment the file is being renamed, it is already CLOSED ].

4.)  As soon as the consumer notices there is a new audio file
     (new "feed"), he opens it, reads its contents, and closes it again.
      (during this time, the producer works in step 1 and 2)
     After closing the file, the consumer(!) erases(!) the file
     (here: "audio.dat"),
     which will cause the producer to jump to step 3, and the whole cycle
     begins from the start.


Details:
--------------------------------------------------------------------------
The producer polls every 100 milliseconds (or so), if he may produce
a new audio file.
The size of the file passed from producer to consumer depends on the
"speed" of the consumer.

To minimize (or even eliminate) hard disk accesses, a RAMDISK can be
used. It is quite out of fashion these days, but it is still possible,
even under Windoze XP. In many cases this is not required because
the operating system often uses a disk cache without "write-through".


Command Line Parameters:
--------------------------------------------------------------------------
 (N = single digit number, NNN=multi-digit integer number,
   the 'equal'-sign can [still?] be left away)

 /dev=N  audio device name (since 2020 for both 'SndInput' and 'SndOutpt')
        If not specified, SndInput.exe uses the default 'Wave Audio'
        input device, which in the windows ecosystem is device "-1" .
        Beware, audio device names under windows can be very strange.
        For example, an Icom IC-7300 (SDR transceiver) appeared as
        "2- USB Audio CODEC" in the system control (classic control
        panel, 'Recording' devices). If a device names contain
        spaces, the device name itself must be double-quoted for the
        command line, e.g.:
           /dev="2- USB Audio CODEC"
        Note: If the device name starts with a NUMBER, the number
        may change when plugging in new USB audio devices, etc.
        To find out the *currently used* name, check the name of
        your audio input devices in the Windows 'classic' audio
        control (possibly somewhere under "Control Panel" / 
        "Hardware and Sound", in german: "Systemsteuerung" / 
        As often under Windows (10), it's much easier to get there
        through the command line: Press the Windows key + 'R'
        to open the 'Run' dialog, enter mmsys.cpl, press ENTER .
        On the classic 'Sound' control, switch to 'Recording'
        (to find device names suitable for "SndInput.exe")
        or to 'Playback'/'Wiedergabe'(?) for "SndOutpt.exe" .
        Each of the audio input devices has two names (in two lines)
        in the list displayed there. The first line shows some
        utterly useless name like "Microphone" / "Mikrofon" /
        "Stereomix" / etc, but you can rename them to a less 
        ambiguous name like "IC-9700" (after discovering that the
          'Microphone (USB Audio CODEC)' is actually your new rig).
        Then, after renaming the device, you can launch the sound
        input utility via e.g.
          SndInput.exe /dev="IC-9700" /sr=4800 /ch=1
        instead of the confusing
          SndInput.exe /dev="2- USB Audio CODEC" /sr=4800 /ch=1 .
        The utility tries to find a matching device even if parts
        of device name are missing, e.g. it will find
          "IC-9700" even if the name return by waveInGetDevCaps() was
          "IC-9700 (2- USB Audio CODEC)" .
        BTW, the full names are also listed in the audio device selector
        (drop-down combo) in Spectrum Lab. The audio-input-utility
        doesn't have such a selector.

        Note to myself: A Behringer U-PHORIA UMC404HD presented its
        FOUR analog inputs as "IN 1-2" and "IN 3-4", thus unfortunately,
        with the standard windows "multimedia" API, it appeared to be
        impossible to open all four analog inputs simultaneously.
        Thus, the only possibilities (with SndInput.exe) were: 
             /dev="IN 1-2" : opens the UMC404's "INPUT 1" and "INPUT 2",
         or  /dev="IN 3-4" : opens the UMC404's "INPUT 3" and "INPUT 4".
        When clicking the "Info"-button, the SndInput-utility
        showed the UMC404 as current 'Input Device' like this:
             "Input Device: 4 IN 1-2 (wave-In)"
         or  "Input Device: 4 IN 3-4 (wave-In)".
        Note the complete lack of the actual 'product name' (UMC404)
        in any of these device- or input channel names 
         - almost as "intuitive" as "2- USB Audio CODEC"
           for an Icom IC-7300 or IC-9700. Ok, 'rant off'.

 /sr=NNN sample rate
        Defines the sampling rate for the ADC (before decimation).
        Usual values are 5512(5513?), 11025, 22050 or 44100;
        on some audio cards also 48000 or even 96000 samples/second.
        Default value: /sr=11025

 /dec=NNN sample rate decimation
        Optional reduction of the sampling rate in den exported data.
        Some 'audiophiles' call this "downsampling",
        in the DAC out tool "Upsamling".
           Default value:  /dec=1 (which means NO decimation).
        Internally, a cascaded design is used,
        every stage consists of a half band filter or "third-
        band-filter", which runs at 1/2 or 1/3 of the sampling rate
        of the preceding stage. A maximum number of 12 stages is
        possible, enough to reduce the (output) sample rate to 1/(2^12)
        or 1/(3^12) of the ADC sampling rate (of course, reducing
        also the usable bandwitdth).
        The shape factor (steepness) of the half-band filter is a bit
        better than the "1/3-band filter", for this reason -if possible-
        use only powers of two for the decimation factor:
                 NNN=2,4,8,..4096.
        The theoretic bandwidth is sr / (2*dec), but practically 
        - due to the filter slope - the usable bandwidth is less, so
        an accurate amplitude measurement is only possible for signals
        within a frequency up to  f = 0.75 * sr/(2*dec),
         for example /sr=11025 /dec=256 -> usable bandwidth ~ 16 Hz .
        Note: For narrow-band signals it's a good idea to use
              floating point numbers for the export file,
              for integer numbers you need a kind of gain factor
              depending on input spectrum if you don't want to waste
              ADC resolution.
        Default value: /dec=1  (no decimation, input rate = output rate)


 /fc=NN.NNN  center frequency for f-conversion with COMPLEX output
 /fr=NN.NNN  center frequency for f-conversion with REAL output
        Optional multiplication of the input signal with a complex
        ("quadrature") sine wave.
        In technical terms, an "NCO" with two outputs, 90 phase lag.
           Default value:  /fc=0
           (which means no frequency shift, real-valued output).
        Only usable (and meaningful)in combination with the sample rate
        decimation ("/dec=NN", NN >= 4 ) .
        The result is either a complex (analytic) or real output signal.
        Use it if only a narrow spectrum around a center frequency (fc)
        in the INPUT SIGNAL are important (fc +- bw/2, with the bandwidth
        of the output signal dictated by the decimation ratio).
        With the "/fc" (complex) option, a monophone signal at the input 
             will be converted into a signal 
             with TWO components (I+Q), a "Stereo-signal" will be turned
             into a data stream with FOUR components per sample point:
               I "left",   Q "left",   I "right",   Q "right".
              (I=in-phase channel, Q=quadrature channel)
          Example for frequency conversion with COMPLEX output:
          SndInput.exe /sr=11025 /fc=2000 /dec=4
             Audio input = 11025 samples/second, 
             Center frequency for 'real' frequency conversion = 2000 Hz
             Decimation ratio = 4
             -> max possible Bandwidth = bw = 11025 / 4 = 2756 Hz (COMPLEX!)
             -> Input frequency band = fc +/- bw/2 = 622 Hz .. 3378 Hz
        The "/fr" option produces REAL output instead; for the same
        decimation ratio it has only half the bandwidth compared to "/fc"
        and only half the data output rate.
          Example for frequency conversion with REAL output:
          SndInput.exe /sr=11025 /fr=2000 /dec=4
             Audio input = 11025 samples/second, 
             Center frequency for 'real' frequency conversion = 2000 Hz
             Decimation ratio = 4
             -> max possible Bandwidth = bw = 11025 / (4*2) = 1378 Hz
             -> Input frequency band = fr +/- bw/2 = 1310 Hz .. 2689 Hz
        To see these parameters in the utility, click the "Info" button.
        Note 1: You can modify the center frequency "on the fly" by typing
                it into an edit field of the utilitie's control window,
                but you cannot change the "conversion mode" this way ! 
        Note 2: The "fr" command is only available for the INPUT tool,
                but not (yet) for SndOutput .


 /ch=N  channels
          /ch1 = one channel,  "mono"
          /ch2 = two channels, "stereo".
           Default value:  /ch=1  (i.e. monophone input)

 /dt=N  data type
        defines the basic data type of the exported audio samples
          1= 8 bit integer  (0..255,  like in 8-bit-WAV-files  )
          2= 16 bit integer (+-32767, like in 16-bit-WAV-files )
          3= 32 bit integer (only rarely supported...)
          4= 64 bit integer (possibly never supported / "reserved for the future")
          5= 32 bit float   ("single precision")
          6= 64 bit float   ("double precision")
        Only the 'floating point' types make sense for decimated samples.
           Default value:  /dt=2  (i.e. 16-bit integer values)


 /gain=NN.NNN  gain (factor!! not a logarithmic scale)
        All samples can be multiplied with an optional "gain" factor before
        turning them into integer values and writing them into a file.
        (Only makes sense, if -for example- decimated samples shall be 
         written to the file as integer values without using too many 
         bits of "resulution".)
           Default value:  /gain=1 (which means NO gain)
        Note: If the data are written as integer values, they may be
              "clipped" if the product (input * gain) gets too large.
              For example, if 8-bit-integers are written, 
              values <0 and >255 will be limited to 0 or 255.

 /dc_reject=N
        Can be used to reject DC-components by software .
         (DC = "direct current" though we mostly use voltages)
        Some audio cards have a strong erroneous DC-component, 
         for example output value from the ADC = -700 
         though the "Line-In" input of the soundcard is only AC-coupled).
           Default value:  /dc_reject=1  (d.h. DC-rejection is ACTIVE)

 /of="<filename>"     output filename   (for all audio INPUT utilities)
 /fn="<filename>"     in- or output filename  (for ALL audio utilities)
        Example: /of="MyAudioStream.dat"
        The default name for the input-and output file is "audio.dat" .
        ( The name of the temporary file is derived from the name
          of the output file, using the extension ".tmp" ).
        If the file name is not chopped into pieces with SPACE characters..
          ( which seems to be common bad practice under Windoze )
        ..you can leave the double quotes away, like
           /of=MyAudioStream.dat  .
           To be compatible with DOS and other operating system,
           DO NOT USE SPACE CHARACTERS IN FILENAMES !  Thanks.
       Location of the output file:
        If you specify a full path for the output file, there's no doubt:
           C:\CBproj\SoundUtl\SndInput.exe /of=C:\Spectrum\audio.dat /ch=1
        If you don't specify a path (or no filename at all), the output
        file will be written into the CURRENT DIRECTORY which was active
        when the tool was launched. This is NOT NECESSARILY the directory
        where the input tool is located !
        If you launch the tool from another location 
        with a full directory path to the executable, like :
           C:\CBproj\SoundUtl\SndInput.exe /ch=1
         while the CURRENT DIRECTORY is something else, for example :
           C:\Spectrum\  
        ...then the output file produced by SndInput will be :
           C:\Spectrum\audio.dat
        ...because the "current directory" will be used if no path 
        is specified.
       

 /chunk=NNNN     audio processing chunk size
        Defines the size of the "portions" which will be read from the
        A/D-converter (or sent to the D/A-converter).
        The smaller this value, the lower is the delay time between
        the analog input and the output to the file;
        but the risk of losing samples caused by task switching and
        other interruptions is increased.
           Default value:  /chunk=2048
        On fast PCs even /chunk=256 works at 11025 samples/sec, 
        but this makes little sense because the server only check
        every 100 milliseconds if a new block from the buffer
        can be written into a file (or vice versa for the DAC tool).


 /minsize=NNNNN  min size of output file
        Defines the minimum size of the output file.
        Default:  /minsize=1K
        NNNN without a letter (suffix) means a size in BYTE,
        with appended letter "k" or "K" it's KBytes (1K = 1024 byte).
        See also: Notes on "/chunk" !

 /maxsize=NNNNN  max size of output file
        Sets the maximum allowed size of the output file
        in BYTE or KBYTE (1 KBYTE = 1024 Byte).
        Default:  /maxsize=64K
        Warning: This default value may be a bit too low for
                   48000 samples/sec * 2 channels * 64-bit-floats
                 because in this (quite academic) case about
                 768 KByte will be written per second !

 /signed=N
        Defines if the A/D converter is connected to a SIGNED
        source (with negative and positive values) or not.
        N=0 means "unsigned values", output value range 0...32767.
        N=1 means "signed values", output range -32768...+32767.
        (Note: the A/D converter in the PIC12F675 microcontroller
               only accepts analog signals from 0...+5V, so it's
               "unsigned" by nature. But you may add an OPAMP
               circuit which adds a bias voltage to the input,
               in this case use the option /signed=1).
        Defaults: /signed=0 for SerInput.exe (ADC on serial interface)
                  /signed=1 for SndInput.exe (soundcard)

 /show=N  initial window 'show' state
        Defines how the window of the utility will be shown
        on program start, and who will be the new "active" window.
          /show=0 :   Minimized window, will not be activated,
                      which means the "calling program" will remain
                      active and will keep the input focus.
                      Win-API-function ShowWindow(SW_SHOWMINNOACTIVE).
          /show=1 :   Normal window, will be activated.
                      Win-API-function ShowWindow(SW_SHOWNORMAL).
          /show=2 :   Normal window, but will NOT be activate .
                      Win-API-function ShowWindow(SW_SHOWNA).
         Default: /show=0   (means the window of the utility
                     will be MINIMIZED and NOT activated. It will run
                     but you only see something in the task bar)

 /display=N   Define what will be displayed in the Tool's window :
          /display=0  Show Time and Count of acquired samples
          /display=1  Show current Values of acquired samples
         Default: /display=0

 /testsig=N.NNN  produce test signal
        Generates a test signal (sine wave) with the given frequency
        in Hertz.
        This feature has been used to test the coninuous replay mode
        and to trace errors caused by too slow file exchange between 
        "producer" and "consumer".
        For the "Sound Input Tool", the sine wave will be written
        into the produced file, 
        for the "Sound Output Tool", it will be sent to the D/A-
        converter in real time.
        The amplitude of the test signal is 6 dB below the maximum
        level. The test signal will be ADDED to the audio samples
        from the A/D-converter, so be careful to avoid overload !
        Note: The frequency of the test signal can be changed
              "on the fly" by typing it into an edit field
              of the utility.

 /port=XXXX  define interface port name
        Defines the port used to receive samples from an external
        A/D converter.
        Only works for SerInput.exe and similar tools for external
        converters. No function for SndInput.exe (which uses the soundcard).
         Default: /port=COM1 

 /fs    fool shell
        A special option to start the utility from a QuickBasic
        program (etc) with the SHELL-command, which seems to wait
        unter Windows XP (and ME, etc?) until the called program
        has terminated (!).
        With this option, the SHELL-command can be fooled.
        How it works and how it can be used: See below, "Program Start".
        Important: If you use the "/fs" option (for example, in a
        batchfile), specify it as the FIRST argument (after the
        program name) so the program can copy the rest of the
        command line, and pass it on to the 2nd launched instance.

 /quit  Automatic closure of the program, useful if the utility
        has been started by another program before.
        Internally, the second started program instance packs the
        command line into a windows message (a WM_COPYDATA message)
        and sends this to the first started instance.
        Finally, both instances terminate themselves.


 Other command line parameters are still "under construction", like:
  - Using the programms as a "normal audio recorder" without time limit,



Display Window
---------------------------------------------------
The display window, aka "GUI", is only used for testing
purposes, because the "main job" of this program is to
work silently in the background.
For this reason, the following displayed values may have been changed
already, or don't exist any longer in the current version:

"TimerTicks" should be incremented every 100ms, if there are no
           uncooperative other programs which steal too much CPU time.
"Samples"  shows how many audio sample points have been acquired since
           the start of the program, and how many of those have been
           passed (via file) to another program.
"TempFile" shows the current size of the temporary file
           (which will be renamed to pass it to the "consumer")


    ________________________________
   |A/D| SndInput    __  [#]  [ x ] |   <- window "title bar"
   |--------------------------------|
   | Timer: 12.3 sec    ,-, ,-, ,-, |
   | Samples: 6543210   | | | | | | |  <- three bargraphs for
   | TempFile: 64 kByte | | | | | | |   bu = "buffer usage",
   | Samples: 6543210   | | | | | | |   vl = "volume left",
   | <error message>    |_| |_| |_| |   vr = "volume right".
   |       ,-------,        ,------,|
   | fr/Hz |0.0    |  ft/Hz | 0.0  ||  <- edit fields
   |       '-------'        '------'|     explained below
   | [Stop]  [Info]  [Gain]  [Quit] |  <- control buttons
   |________________________________|
       


There are also a few edit-fields in the control window which CAN be
used to modify certain parameters without stopping the process:

"fr/Hz" or "fc/Hz": An edit field for the center frequency,
           if the optional frequency conversion is enabled. 
           See explanation of the commands "/fc" or "/fr" .
           (fr=frequency conversion with REAL output,
            fc=frequency conversion with COMPLEX output)
"ft/Hz"    This edit field can be used to change the frequency 
           of the "test signal" on the fly.
           See explanation of the "/testsig" command.
             

At the right side of the window some vertical bars are displayed, 
among them a "buffer level indicator" and a simple level meter.
The indicated audio level (in PERCENT of the clipping level)
should be below 70 % . Otherwise you can start the program 
"sndvol32" (Windoze "sound volume control") with the "GAIN" button.
Unfortunately Microsoft have the bad habit to change the names
of these 'built-in utilities', so depending on the windows version,
the name may be "sndvol.exe" instead of "sndvol32.exe", or whatever
comes next in Windows 10, 11, etc.
Thus, don't be surprised if clicking the "Gain"-button
has no effect (in that case, try to find the right
volume- or input-gain-control application yourself).



Info-Window
---------------------------------------------------
Shows the program version (and/or compilation date),
contents of the command line when the program was started
and a few other parameters.


Installation
---------------------------------------------------
Should not be required. The program does not require any
"special" DLLs. Just copy it to any directory you like.
On the author's PC, both utilities are kept in the folder
c:\CBproj\SoundUtl\*.*, some links in HTML files point
to this directory.


Sourcecodes
---------------------------------------------------
The sources were initially compiled with Borland C++ Builder
Version 4,  but most of them can be compiled (and linked)
with DevCpp V4.9.9.2 too (which seems to be the last
version of that nice freeware development system).
The sources are available on the author's website, 
      www.qsl.net/dl4yhf/snd_utl1.html
at the time of this writing.


Program start and termination
---------------------------------------------------
You can start the program from your own application with
a SHELL-command (in Basic), "WinExec", "ShellExecute" etc.
Or you create a shortcut on the desktop which includes
the full command line with all required arguments as described
above.

To terminate the program, restore the window to its normal
size and click the "QUIT" button or the close symbol ("X")
in the upper right corner.

It is also possible to terminate the program from another 
("user-")program by "calling" it again with the command 
line "/quit". 
For a very short time, two instances of the utility will run, 
but the second instance will detect the first program instance
and pass the whole command line (with the "/quit"-instruction) 
to the first instance using a WM_COPYDATA-message. 
Finally, both instances will terminate themselves.



The "Fool Shell"-option (/fs)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
  (ask me to translate this into english if you need it...)
Beim Aufruf des Programmes aus QuickBasic unter Windoze XP
zeigte sich das Problem, dass das Programm im SHELL-Kommando
"hing", bis das SoundInput-Utility beendet war.
Um dieses Problem zu umgehen, kann
    ALS ERSTER PARAMETER IN DER KOMMANDOZEILE
der Schalter "/fs" stehen (fs wie "fool [the] shell").
Dieser bewirkt, dass das Utility sich selbst nochmal startet, wobei
der Rest der Kommandozeile hinter dem "/fs" an die zweite Instanz
weitergegeben wird. Unmittelbar danach beendet sich die erste
Instanz selbst.
Der SHELL-Befehl von QuickBasic kriegt von diesem Betrug nichts mit, 
und arbeitet wie gewnscht weiter.
 Beispiel (Aufruf aus QuickBasic-Programm) :
  SHELL "sndinput.exe /fs /dt=1 /sr=5512 /ch=2 /maxsize=32k"

Das Utility analysiert die Kommandozeile von links nach rechts. Die
"/fs"-Option wird erkannt, und automatisch eine neue Kommandozeile
zusammengesetzt (mit dem kompletten Pfad zum EXE-File und dem Rest der
Kommandozeile):
    c:\QuickBasic\SndInput.exe /dt=1 /sr=5512 /ch=2
Dieses Kommando wird mit Hilfe einer Win32-API-Funktion gestartet,
die -im Gegensatz zum SHELL-Befehl- sofort zurckkehrt.
Die zuerst gestartete Instanz terminiert sich danach sofort selbst,
damit das aufrufende BASIC-Programm (o.ae.) weiterlaeuft.

Mit einer leichten Modifikation konnte die "fool shell"-Option auch
unter Windows 8.1 in der Windows-eigenen Shell ("Konsolenfenster")
wieder 'zum Laufen' gebracht werden, so dass auch der Aufruf aus
'Batch-Dateien' nicht mehr dazu fhrt, dass Windows (8.1 & Co?)
nicht mehr wartet, bis sich das aus dem Batch gestartete Programm
(in diesem Fall SndInout.exe oder SndOutpt.exe) selbst beendet hat.


Viel Erfolg bei eigenen Experimenten mit 'DSP per Soundkarte' / good luck,

 Wolfgang Buescher (DL4YHF@qsl.net) .

