====== Simulating Analog Audio Cicuits ====== {{:wiki:spicesound.png?250 }} This article describes an extension to //ngspice// that provides a //libsndfile// voltage source and the possibility to write //ngspice//'s output in audio-file format. **Ngspice** is a mixed-level/mixed-signal circuit simulator, based on Berkeley Spice3F5 and developed openly as [[http://ngspice.sf.net|ngspice sourceforge project]]. (see [[wp>SPICE]]) **Libsndfile** is a C library for reading and writing files containing sampled sound; released in [[http://www.mega-nerd.com/libsndfile/|source]] code format under the GNU Lesser General Public License. ====== Spicy Sound ====== The idea is simple: use a schematic as audio-effect. When compared to //traditional// digital audio effects, performing a full analog circuit simulation breaks a fly on the wheel. However todays computing power allows to do so almost in real-time! But don't get your hopes up too soon.. even if passing 10 seconds 48kHz audio though a simulated RC bandpass takes 11.2 seconds on a 1.6Ghz pentium, it's far far away.. Nevertheless being able to process arbitrary audio-samples with [[wp>SPICE]] provides off-line sound processing and (re-)engineering features for analog audio circuits. In this exercise the audio-input represents a linear sound-controlled voltage-source in the schematic and the audio-sink can be any node in the schematic's netlist. ===== Preparation / Source Code ===== Though spice is rather flexibly importing/exporting data, adding native sound I/O functionality greatly improves performance, simplifies prototyping and shortens turnaround time at the cost of (re-)compiling ngspice ((earlier versions of the patch include a simple tool to convert spice ''.print'' text to sound. - see [[txt2snd]])). The patch applies to the ngspice-rework17 source code release and does not modify exiting functionality of ngspice . It just adds new features, and also works with the current CVS version of ngspice. * {{ng-spice-rework-17-snd-v3.2.diff}} - fixed start-offset * {{ng-spice-rework-17-snd-v3.diff}} - added resampling/oversampling (requires libsamplerate) * {{ng-spice-rework-17-snd-v2.diff}} Apart from ngspice' build-dependencies, you need the **libsndfile-dev** package to compile it: cd /tmp wget http://downloads.sourceforge.net/ngspice/ng-spice-rework-17.tar.gz wget http://gareus.org/_media/oss/spicesound/ng-spice-rework-17-snd-v3.2.diff tar xzf ng-spice-rework-17.tar.gz cd ng-spice-rework-17 patch -p1 < ../ng-spice-rework-17-snd-v3.2.diff ./autogen.sh mkdir build && cd build ../configure && make sudo make install \\ **UPDATE**: Hannu Vuolasaho rebased the patch to spice-0.23. The patch and information is available on [[http://sourceforge.net/tracker/?func=detail&aid=3408334&group_id=38962&atid=423917]] ===== Syntax ===== See the chapter [[http://newton.ex.ac.uk/teaching/CDHW/Electronics2/userguide/sec3.html#3.2|Voltage and Current Sources]] in the [[http://newton.ex.ac.uk/teaching/CDHW/Electronics2/userguide/|spice3 user manual]] for general information. ==== Audio Source ==== The //snd patched// spice knows a new type of [[http://newton.ex.ac.uk/teaching/CDHW/Electronics2/userguide/sec3.html#3.2.1|Independent voltage source]] extending the syntax of VXXXXXXX N+ N- < DC/TRAN VALUE> >> + >> >> with the time-dependent value: **Syntax:** FILE(FILENAME) SND (ID V_OFFSET V_MULT T_OFF CHANNEL OVERSAMPLING **Examples:** V_V2 10 0 dc 0.0 file /tmp/stay.wav snd 0 0 0.2 0 0 1 VLEFT 2 0 file(/TmP/tEst.wAv) snd 1 0 0.2 5.0 0 64 VRIGHT 13 2 snd(1 0.0 1.0 5.0 1 64) **Description** N+ and N- are the positive and negative nodes, and the //new// parameters are * an integer identifier 0 to 5 * offset added in Volts * the multiplier when converting sndfile-float [0..1] to Volts * offset in seconds added when seeking the sound-file * the sound channel to use. 0: first channel in file. * //new in v3// allows to upsample the audio-file. - see synchronization below * The optional parameter must precede the argument to take affect. * Note: spice syntax treats all filenames as lowercase. Spaces and special characters are not allowed in the filename either. * if no filename is specified the previous filename for the given is used. Default files are id=0:/tmp/test.wav id=1:/tmp/test1.wav id=2..N://NULL// If unspecified spice uses default TSTEP and TSTOP for transient analysis, which should match the sampling rate of the audio file times the oversampling factor. - unless you know what you're doing: choose the same oversampling-factor for input and output. Read more about synchronization in the next section. ==== Sink ==== Converting spice's output into a sound file is done with a standard [[http://newton.ex.ac.uk/teaching/CDHW/Electronics2/userguide/sec4.html#4.4.2|print]] command. ''sndprint'' behaves just like ''print'' with the difference that it does not write text to screen but the same values into a audio file instead. each ''sndprint'' argument gets written as a channel in the file. The //global// parameters (filename, samplerate) can be changed for each ''sndprintf''. **Syntax:** .PRINT PRTYPE OV1 [ OV2 ... OV8 ] .SNDPARAM FILENAME [ SAMPLERATE [FORMAT [V_OFF [V_MULT] [OVERSAMPLING] ] ] ] .SNDPRINT PRTYPE OV1 [ OV2 ... OV8 ] **Examples:** .sndparam /tmp/spice-1.wav 48000 wav16 3.0 0.0 64 .sndprint tran v(10) v(9) .sndparam /tmp/spice-2.wav 48000 wav24 .sndprint tran v(10) **Description** ''sndparam'' affects all following ''.sndprint'' lines. If not specified the defaults values are used: ''.sndparam spice.wav 48000 -1 0.0 1.0 64''. * of the output file - it will be converted to lower case and must not contain spaces or special characters. * is the number of audio-samples to write in 1/s * - numeric or text-shortcut. * -1:default (wav 24 bit/sample little endian) * 0: aliki .ald data file * >0 : //libsndfile// [[http://www.mega-nerd.com/libsndfile/api.html|numeric format]] SF_FORMAT_XXX - example: (SF_FORMAT_WAV | SF_FORMAT_PCM_24) = 0x010000 | 0x003 = 65539 * currently the following txt shortcuts are defined: ''wav16'', ''wav24'', ''wav32'', ''aiff'' and ''aliki''. * is an offset voltage added after multiplication * specifies a multiplier to extend the dynamic range or normalize the value. * //new in v3// allows to downsample/interpolate when writing the file. The output range of ''sndprint'' is [-1..1] - values are clipped. Each printed parameter will be written to a separate audio-channel; fi. ''sndprint v(2)'' writes a mono file from the voltage of net 2; ''sndprint v(2) v(4)'' produces a stereo file. - The ''sndparam'' conversion parameters are set per file and apply for all channels to be written. ====== Further Information ====== ===== Synchronization ===== Spice allows to specify a maximum time-step, which should be set to the audio-sample rate. The step-size is not guaranteed and sometimes smaller than the specified value, which makes synchronization a non trivial problem. Unlike the [[txt2snd]] tool, the internal ''sndprint'' does not add missing samples. ''sndprint'' only drops excess samples and does not perform any resampling or interpolation; thus ''sndprint'' should only be used when simulating at audio-samplerate or even shorter interval which should best be at an integer multiple of the samplerate. simulating 5 seconds at 1/48000Hz: .tran 2.0833333333333e-05 5.0 0 2.0833333333333e-05 when using oversampling, the time step needs to be adjusted accordingly! .tran 3.25520833e-07 3.0 0 3.25520833e-07 Note: the simulation time-step must be smaller than the 1sec/(sndprint_samplerate*sndprint_oversampling). ===== Examples ===== simple audio test V_V2 1 0 file /tmp/test.wav snd 0 0 1.0 0 0 R_R1 1 0 1M .sndparam /tmp/test-spice.wav 48000 wav24 1.0 0.0 .sndprint tran v(1) .tran 2.08333e-05 2.0 0 2.08333e-05 .op .END Save this file as ''sndtst.cir'' copy //any// audio-file (longer than 2 seconds) to ''/tmp/test.wav''. Launch the simulation: ''spice -b sndtst.cir'' will generate /''tmp/test-spice.wav'' - this example simply copies the first two secods of audio from the channel of the audio-file into a 24bit 48kHz mono wav file. more [[examples]]. ===== Developer Notes ===== This patch is rather a quick experiment; already very useful though. There are some open-ends, that will be fixed after testing and receiving feedback on the patch: Most notably are verifying the command arguments; checking for libsndfile in configure.in; and printing nice warnings/statistics for missing/skipped audio-samples. Other addons that could come in handy, would be implementing different algorithms of converting the sound into a spice-value and back (eg. logarithmic scale, linear resampling, current source) though I dare say that can be done with ngSPICE functions already. - Before settling on the ''sndprint'' command I considered using a resistor or inductance based model for a "speaker" that could be wired into the schematic and write the sound to file during the simulation. ''sndprint'' is more flexible. ====== References ====== * [[http://sourceforge.net/project/showfiles.php?group_id=38962&package_id=31152&release_id=352845|ngspice source code]] * [[http://newton.ex.ac.uk/teaching/CDHW/Electronics2/userguide/|spice3]] HTML user manual * [[http://www-ti.informatik.uni-tuebingen.de/~bernauer/lehre/ti-1-0506/spice/ngspice.pdf|PDF manual]] for ngspice * [[sf>ngspice|ngSPICE soureforge project]] site * http://ngspice.sf.net - ngSpice website * [[http://www.mega-nerd.com/libsndfile/|libsndfile]] {{tag>FLOSS MUSIX}}