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.
Libsndfile is a C library for reading and writing files containing sampled sound; released in source code format under the GNU Lesser General Public License.
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 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.
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 1).
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.
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
The snd patched spice knows a new type of Independent voltage source extending the syntax of
VXXXXXXX N+ N- <<DC> DC/TRAN VALUE> <AC <ACMAG <ACPHASE>>> + <DISTOF1 <F1MAG <F1PHASE>>> <DISTOF2 <F2MAG <F2PHASE>>>
with the time-dependent value:
FILE(FILENAME) SND (ID V_OFFSET V_MULT T_OFF CHANNEL OVERSAMPLING
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)
N+ and N- are the positive and negative nodes, and the new parameters are
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.
Converting spice's output into a sound file is done with a standard print command.
sndprint behaves just like
sndprint argument gets written as a channel in the file. The global parameters (filename, samplerate) can be changed for each
.PRINT PRTYPE OV1 [ OV2 ... OV8 ]
.SNDPARAM FILENAME [ SAMPLERATE [FORMAT [V_OFF [V_MULT] [OVERSAMPLING] ] ] ] .SNDPRINT PRTYPE OV1 [ OV2 ... OV8 ]
.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)
sndparam affects all following
.sndprint lines. If not specified the defaults values are used:
.sndparam spice.wav 48000 -1 0.0 1.0 64.
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.
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).
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.
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.