diff --git a/src/Makefile.am b/src/Makefile.am
index 74e16ce..5786300 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -37,6 +37,7 @@ qucsator_LDADD = libqucsator.a		      \
 	components/microstrip/libmicrostrip.a \
 	components/devices/libdevices.a	      \
 	components/digital/libdigital.a       \
+	-lsndfile -lsamplerate \
 	components/verilog/libverilog.a
 
 qucsator_SOURCES = ucs.cpp circuit.cpp check_netlist.cpp operatingpoint.cpp  \
@@ -51,6 +52,7 @@ noinst_TEMPLATES = tmatrix.cpp eqnsys.cpp nasolver.cpp states.cpp tvector.cpp \
 	ptrlist.cpp tridiag.cpp hash.cpp valuelist.cpp nasolution.cpp
 
 noinst_HEADERS = $(noinst_TEMPLATES) check_netlist.h complex.h input.h net.h  \
+	sndprint.h
 	tokens_netlist.h dataset.h logging.h node.h property.h vector.h       \
 	tokens_dataset.h check_dataset.h strlist.h tokens_touchstone.h        \
 	check_touchstone.h matrix.h analysis.h spsolver.h dcsolver.h object.h \
@@ -67,6 +69,7 @@ noinst_HEADERS = $(noinst_TEMPLATES) check_netlist.h complex.h input.h net.h  \
 noinst_LIBRARIES = libqucsator.a
 
 libqucsator_a_SOURCES = dataset.cpp check_dataset.cpp parse_dataset.cpp     \
+	sndprint.c \
 	scan_dataset.cpp check_touchstone.cpp vector.cpp object.cpp         \
 	property.cpp parse_touchstone.cpp scan_touchstone.cpp variable.cpp  \
 	complex.cpp strlist.cpp logging.c exception.cpp exceptionstack.cpp  \
diff --git a/src/check_netlist.cpp b/src/check_netlist.cpp
index 2bb57f8..248e824 100644
--- a/src/check_netlist.cpp
+++ b/src/check_netlist.cpp
@@ -205,6 +205,13 @@ static struct special_t checker_specials[] = {
 			       NULL } },
   { "DC",     "Solver",      { "CroutLU", "DoolittleLU", "HouseholderQR",
 			       "HouseholderLQ", "GolubSVD", NULL } },
+  { "TSOUND",     "Type",        { "lin", "log", NULL } },
+  { "TSOUND",     "IntegrationMethod",
+    { "Euler", "Trapezoidal", "Gear", "AdamsMoulton", NULL } },
+  { "TSOUND",     "Solver",      { "CroutLU", "DoolittleLU", "HouseholderQR",
+			       "HouseholderLQ", "GolubSVD", NULL } },
+  { "TSOUND",     "relaxTSR",    { "yes", "no", NULL } },
+  { "TSOUND",     "initialDC",   { "yes", "no", NULL } },
   { "TR",     "Type",        { "lin", "log", NULL } },
   { "TR",     "IntegrationMethod",
     { "Euler", "Trapezoidal", "Gear", "AdamsMoulton", NULL } },
@@ -343,6 +350,15 @@ static int checker_resolve_variable (struct definition_t * root,
     if ((val = checker_find_variable (root, "SPfile", "File", value->ident))) {
       found++;
     }
+    if ((val = checker_find_variable (root, "Vsnd", "File", value->ident))) {
+      found++;
+    }
+    if ((val = checker_find_variable (root, "TSOUND", "File", value->ident))) {
+      found++;
+    }
+    if ((val = checker_find_variable (root, "TSOUND", "Format", value->ident))) {
+      found++;
+    }
     /* 7. find variable in equation */
     if (root->env->getChecker()->containsVariable (value->ident)) {
       variable * v;
diff --git a/src/components/Makefile.am b/src/components/Makefile.am
index 4a5a55c..b42961d 100644
--- a/src/components/Makefile.am
+++ b/src/components/Makefile.am
@@ -29,6 +29,7 @@ SUBDIRS = microstrip devices digital verilog
 noinst_LIBRARIES = libcomponent.a
 
 libcomponent_a_SOURCES = attenuator.cpp dcblock.cpp open.cpp vccs.cpp        \
+	vsjack.c vsnd.cpp \
 	biastee.cpp circulator.cpp dcfeed.cpp pac.cpp vcvs.cpp capacitor.cpp \
 	ground.cpp resistor.cpp cccs.cpp cross.cpp trafo.cpp inductor.cpp    \
 	tee.cpp ccvs.cpp isolator.cpp itrafo.cpp strafo.cpp vdc.cpp idc.cpp  \
@@ -39,6 +40,7 @@ libcomponent_a_SOURCES = attenuator.cpp dcblock.cpp open.cpp vccs.cpp        \
 	vpm.cpp tswitch.cpp relais.cpp short.cpp twistedpair.cpp tline4p.cpp
 
 noinst_HEADERS = attenuator.h dcblock.h open.h vccs.h biastee.h circulator.h \
+	vsjack.h vsnd.h \
 	dcfeed.h pac.h vcvs.h capacitor.h ground.h resistor.h cccs.h cross.h \
 	trafo.h inductor.h tee.h ccvs.h isolator.h component.h itrafo.h      \
 	strafo.h vdc.h idc.h vac.h component_id.h phaseshifter.h gyrator.h   \
diff --git a/src/components/component.h b/src/components/component.h
index cfd9597..00cc901 100644
--- a/src/components/component.h
+++ b/src/components/component.h
@@ -58,6 +58,7 @@
 #include "vdc.h"
 #include "idc.h"
 #include "vac.h"
+#include "vsnd.h"
 #include "iac.h"
 #include "vam.h"
 #include "vpm.h"
diff --git a/src/components/vsjack.c b/src/components/vsjack.c
new file mode 100644
index 0000000..05af9f4
--- /dev/null
+++ b/src/components/vsjack.c
@@ -0,0 +1,229 @@
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+
+/////// SNDFILE ///////
+#include <stdlib.h>
+#include <math.h>
+#include <sndfile.h>
+#include <inttypes.h>
+#define VS_BUFSIZ 1024
+
+#define MAX_D 6 
+char *(sources[MAX_D]);
+
+SNDFILE * m_sndfile[MAX_D]; 
+int m_channels[MAX_D]; //< number of channles in src-file
+uint32_t m_samplerate[MAX_D]; //< samplerate of source
+uint32_t m_frames[MAX_D]; //< duration of source in frames
+float *(interleaved[MAX_D]); //< internal soundfile buffer
+uint32_t ilb_start[MAX_D]; //< first sample in buffer 
+uint32_t ilb_end[MAX_D]; //< last sample in buffer
+
+#define HAVE_SRC
+
+#ifdef HAVE_SRC
+#include <samplerate.h>
+double src_ratio=64.0;
+#define SRC_RATIO src_ratio
+SRC_STATE *rabbit[MAX_D];
+int rabbit_err[MAX_D];
+float *(resampled[MAX_D]); //< internal soundfile buffer
+#endif
+
+void vsjack_initialize(void) {
+	int d;
+	for (d=0;d<MAX_D;d++) {
+		m_sndfile[d]=NULL;
+		interleaved[d]=NULL;
+#ifdef HAVE_SRC
+		resampled[d]=NULL;
+#endif
+		sources[d]=NULL;
+	}
+	sources[0]=strdup("/tmp/test.wav");
+	sources[1]=strdup("/tmp/test1.wav");
+}
+
+void realloc_sf (int d, uint32_t buffersize) {
+	if (interleaved[d]) free(interleaved[d]);
+	interleaved[d] = (float *) calloc(m_channels[d]*buffersize, sizeof(float));
+}
+
+#ifdef HAVE_SRC
+void realloc_src (int d, uint32_t buffersize) {
+	if (resampled[d]) free(resampled[d]);
+	resampled[d] = (float *) calloc(m_channels[d]*buffersize, sizeof(float));
+}
+#endif
+
+#if 0
+void closefile_sf(int d) {
+    if (!m_sndfile[d]) return;
+    sf_close(m_sndfile[d]);
+#ifdef HAVE_SRC
+    src_delete(rabbit[d]);
+#endif
+    m_sndfile[d]=NULL; 
+}
+#endif
+
+int openfile_sf (int d, char *filename) {
+    SF_INFO sfinfo;
+    if (!m_sndfile[d]) sf_close(m_sndfile[d]);
+    printf("opening file '%s' for id:%i\n",filename, d);
+    m_sndfile[d] = sf_open( filename, SFM_READ, &sfinfo );	
+    ilb_end[d]=ilb_start[d]=0;
+    
+    if ( SF_ERR_NO_ERROR != sf_error( m_sndfile[d] ) ) {
+	fprintf(stderr, "This is not a sndfile supported audio file format\n");
+	return (-1);
+    }
+    if ( sfinfo.frames==0 ) {
+	fprintf(stderr, "This is an empty audio file\n" );
+	return (-1);
+    }
+    m_channels[d] = sfinfo.channels;
+    m_samplerate[d] = sfinfo.samplerate;
+    m_frames[d] = (uint32_t) sfinfo.frames;
+    realloc_sf(d, VS_BUFSIZ);
+#ifdef HAVE_SRC
+    realloc_src(d, VS_BUFSIZ*SRC_RATIO);
+    rabbit[d]=src_new(SRC_SINC_BEST_QUALITY, m_channels[d], &(rabbit_err[d]));
+    src_set_ratio(rabbit[d], SRC_RATIO);
+    src_reset(rabbit[d]);
+#endif
+    return (0);
+}
+
+void load_buffer(int d, uint32_t sample) {
+    sf_seek( m_sndfile[d], sample, SEEK_SET );
+    ilb_start[d] = sample;
+    uint32_t nframes;
+    if ((nframes=sf_readf_float(m_sndfile[d], (interleaved[d]), VS_BUFSIZ))>0) {
+	ilb_end[d] = ilb_start[d] + nframes; 
+    } else {
+	ilb_end[d] = ilb_start[d];
+	printf ("Decoder error after seek %u.\n",sample);
+    }
+    //printf("DEBUG sample buffer: %i -> %i\n",ilb_start[d],ilb_end[d]);
+#ifdef HAVE_SRC
+    SRC_DATA src_data;
+    src_data.data_in = interleaved[d];
+    src_data.data_out = resampled[d];
+    src_data.input_frames  = VS_BUFSIZ;
+    src_data.output_frames = VS_BUFSIZ*SRC_RATIO;
+    src_data.end_of_input  = ((ilb_end[d]-ilb_start[d]) < VS_BUFSIZ); // FIXME; check for non-continuity, too!
+    src_data.src_ratio     =  SRC_RATIO;
+    src_data.input_frames_used = 0;
+    src_data.output_frames_gen = 0;
+
+    //src_set_ratio(rabbit[d], SRC_RATIO); // FIXME - only when it changes see below
+    src_process(rabbit[d], &src_data);
+#endif
+}
+
+double get_value(int d, double time, int channel) {
+    uint32_t sample = (uint32_t) floor(time*((double)m_samplerate[d]));
+
+    // TODO: print EOF warning (once). FIXME move to load_buffer
+    if (sample > m_frames[d] ) return (0.0);
+
+    if (sample < ilb_start[d] || sample >= ilb_end[d]) 
+	load_buffer(d, (sample>1)? sample -1: sample);
+
+    if (sample < ilb_start[d] || sample >= ilb_end[d]) {
+	printf ("no such value buffered for file:%i.\n",d);
+	return (0.0); // nan ?
+    }
+
+#ifdef HAVE_SRC
+    int offset = floor((sample - ilb_start[d])*SRC_RATIO);
+    if (offset > VS_BUFSIZ*SRC_RATIO || offset < 0) {
+	printf ("value not in buffer:%i.\n",d);
+	return (0.0); // nan ?
+    }
+    float val = ((float *)(resampled[d]))[m_channels[d]*offset+channel];
+#   if 0 // progress
+    static int dev_cnt = 0;
+    if ((dev_cnt%((int)floor(SRC_RATIO*0.001*((double)m_samplerate[d]))))==0) 
+	printf (" tme:%e sample:%i oss:%e iter:%i\n",time, sample, (sample*SRC_RATIO), dev_cnt++);
+#   endif
+#   if 0 // DEBUG 
+#   define SQUARE(A) ((A)*(A))
+    static double stride =0.0;
+    static double last =0.0;
+    static double deviation =0.0;
+    static int dev_cnt = 0;
+    if (channel == 0 && time>0.09) {
+	stride += SQUARE((SRC_RATIO*time*((double)m_samplerate[d])) - last);
+	deviation += SQUARE((SRC_RATIO*time*((double)m_samplerate[d])) - floor(SRC_RATIO*time*((double)m_samplerate[d])));
+	dev_cnt ++;
+	if ((dev_cnt%(8000))==0) 
+	    printf ("@%e[~%e] avgs: read time dev= %e - stride= %e\n",time,
+	     //((SRC_RATIO*time*((double)m_samplerate[d])) - floor(SRC_RATIO*time*((double)m_samplerate[d]))), 
+	     ((SRC_RATIO*time*((double)m_samplerate[d])) - last), 
+	     sqrt(deviation/(double)dev_cnt), sqrt(stride/(double)dev_cnt));
+    } 
+    if (channel == 0 ) 
+	last = (SRC_RATIO*time*((double)m_samplerate[d]));
+#   endif 
+# if 0 // zero order hold.
+    return((double)val);
+# else
+    // linear interpolation
+    float val1 = ((float *)(resampled[d]))[(m_channels[d]*(offset+1))+channel];
+    double diff = (SRC_RATIO*time*((double)m_samplerate[d])) -
+		  floor(SRC_RATIO*time*((double)m_samplerate[d]));
+    double rv = ((double)val)*(1.0-diff) + ((double)val1)*diff;
+    return(rv);
+# endif
+
+#else // no upsampling.
+
+    int offset = sample - ilb_start[d];
+    if (offset > VS_BUFSIZ || offset < 0) {
+	printf ("value not in buffer:%i.\n",d);
+	return (0.0); // nan ?
+    }
+    return((double)(((float *)(interleaved[d]))[m_channels[d]*offset+channel]));
+#endif
+}
+
+
+/*
+ * "public" functions
+ */
+
+double vsjack_get_value (int d, double time, double time_offset, int channel, double oversampling) {
+    assert (d>=0 && d< MAX_D );
+    if (m_sndfile[d] == NULL) return (0.0); // FIXME
+    if (oversampling > 0) src_ratio = oversampling; // FIXME - realloc & flush buffer on change && src_set_ratio()
+
+    double value = get_value(d, time+time_offset, channel);
+    return (value);
+}
+
+void vsjack_set_file (int d , char *fn) {
+    assert (d>=0 && d< MAX_D );
+    if (sources[d] != NULL) free (sources[d]);
+    sources[d] = strdup(fn);
+}
+
+int vsjack_open (int d) {
+    static int initialized =0;
+    if (!initialized) {
+	initialized=1;
+	vsjack_initialize();
+    }
+    if (d==-1) return -1;// initialize only
+    assert (d>=0 && d< MAX_D );
+    assert (sources[d]!=NULL);
+    if (openfile_sf(d, sources[d])) {
+	printf ("could not open '%s'\n", sources[d]);
+	exit (1);
+    }
+    return (d);
+}
+
+/* vi:set ts=8 sts=4 sw=4: */
diff --git a/src/components/vsjack.h b/src/components/vsjack.h
new file mode 100644
index 0000000..fe151a6
--- /dev/null
+++ b/src/components/vsjack.h
@@ -0,0 +1,4 @@
+
+double vsjack_get_value (int, double, double, int, double);
+int vsjack_open (int);
+void vsjack_set_file (int, char*);
diff --git a/src/components/vsnd.cpp b/src/components/vsnd.cpp
new file mode 100644
index 0000000..173b44c
--- /dev/null
+++ b/src/components/vsnd.cpp
@@ -0,0 +1,109 @@
+/*
+ * vsnd.cpp - Sound voltage source class implementation
+ *
+ * Copyright (C) 2003, 2004, 2006, 2007 Stefan Jahn <stefan@lkcc.org>
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ * 
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this package; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+ * Boston, MA 02110-1301, USA.  
+ *
+ * $Id: vsnd.cpp,v 1.19 2007/03/11 15:43:10 ela Exp $
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "complex.h"
+#include "object.h"
+#include "node.h"
+#include "circuit.h"
+#include "net.h"
+#include "component_id.h"
+#include "consts.h"
+#include "constants.h"
+#include "vsnd.h"
+
+extern "C" {
+#include "vsjack.h"
+}
+
+vsnd::vsnd () : circuit (2) {
+  type = CIR_VAC;
+  setVSource (true);
+  setVoltageSources (1);
+}
+
+void vsnd::initSP (void) {
+  allocMatrixS ();
+  setS (NODE_1, NODE_1, 0.0);
+  setS (NODE_1, NODE_2, 1.0);
+  setS (NODE_2, NODE_1, 1.0);
+  setS (NODE_2, NODE_2, 0.0);
+}
+
+void vsnd::initDC (void) {
+  allocMatrixMNA ();
+  voltageSource (VSRC_1, NODE_1, NODE_2);
+}
+
+void vsnd::initAC (void) {
+  initDC ();
+  setE (VSRC_1, 0.0);
+}
+
+void vsnd::initTR (void) {
+  initDC ();
+  char *fn;
+  vsjack_open(-1); 
+  if ((fn=getPropertyString ("File"))) {
+  	printf("set sound-file name:%s\n",fn);
+	  vsjack_set_file(0,fn);
+  }
+  vsjack_open(0);
+}
+
+void vsnd::calcTR (nr_double_t t) {
+  nr_double_t o = getPropertyDouble ("Oversampling");
+  int c = getPropertyInteger ("Channel");
+  nr_double_t m = getPropertyDouble ("U");
+  nr_double_t v = getPropertyDouble ("Uoffset");
+  nr_double_t to = getPropertyDouble ("TimeOffset");
+  nr_double_t s = getNet()->getSrcFactor ();
+  nr_double_t u = m * s * vsjack_get_value(0, t, to, c, o);
+  setE (VSRC_1, u+v);
+}
+
+void vsnd::initHB (void) {
+  setVoltageSources (1);
+  allocMatrixMNA ();
+  voltageSource (VSRC_1, NODE_1, NODE_2);
+}
+
+void vsnd::calcHB (nr_double_t frequency) {
+  nr_double_t f = getPropertyDouble ("f");
+  if (f == frequency) {
+    nr_double_t a = getPropertyDouble ("U");
+    nr_double_t p = getPropertyDouble ("Phase");
+    setE (VSRC_1, polar (a, rad (p)));
+  }
+  else {
+    setE (VSRC_1, 0);
+  }
+}
diff --git a/src/components/vsnd.h b/src/components/vsnd.h
new file mode 100644
index 0000000..b32c9b8
--- /dev/null
+++ b/src/components/vsnd.h
@@ -0,0 +1,41 @@
+/*
+ * vsnd.h - SOUND voltage source class definitions
+ *
+ * Copyright (C) 2003, 2004, 2006 Stefan Jahn <stefan@lkcc.org>
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ * 
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this package; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+ * Boston, MA 02110-1301, USA.  
+ *
+ * $Id: vsnd.h,v 1.10 2006/03/29 08:02:03 raimi Exp $
+ *
+ */
+
+#ifndef __VSND_H__
+#define __VSND_H__
+
+class vsnd : public circuit
+{
+ public:
+  vsnd ();
+  void initSP (void);
+  void initDC (void);
+  void initAC (void);
+  void initTR (void);
+  void calcTR (nr_double_t);
+  void initHB (void);
+  void calcHB (nr_double_t);
+};
+
+#endif /* __VSND_H__ */
diff --git a/src/converter/Makefile.am b/src/converter/Makefile.am
index 6a8da1b..8509ed0 100644
--- a/src/converter/Makefile.am
+++ b/src/converter/Makefile.am
@@ -26,7 +26,7 @@ EXTRA_DIST = parse_spice.y scan_spice.l parse_vcd.y scan_vcd.l
 
 bin_PROGRAMS = qucsconv
 
-qucsconv_LDADD = ../libqucsator.a
+qucsconv_LDADD = ../libqucsator.a -lsndfile -lsamplerate
 
 INCLUDES = -I$(top_srcdir)/src
 
diff --git a/src/dataset.cpp b/src/dataset.cpp
index b854ba8..9c14c5d 100644
--- a/src/dataset.cpp
+++ b/src/dataset.cpp
@@ -322,11 +322,17 @@ void dataset::setFile (const char * f) {
   file = f ? strdup (f) : NULL;
 }
 
+extern "C" {
+#include "sndprint.h"
+}
+
 /* This function prints the current dataset representation either to
    the specified file name (given by the function setFile()) or to
    stdout if there is no such file name given. */
 void dataset::print (void) {
 
+  if (!printSndfile()) return;
+
   FILE * f = stdout;
 
   // open file for writing
@@ -358,6 +364,42 @@ void dataset::print (void) {
   if (file) fclose (f);
 }
 
+int dataset::printSndfile (void) {
+  int c=0;
+  vector *tme = dependencies; //data->findDependency ("time"))
+  int len=tme->getSize();
+
+  printf("sndprint start\n");
+
+  for (vector * v = variables; v != NULL; v = (vector *) v->getNext ()) 
+    if (v->getDependencies () != NULL && len == v->getSize() && strstr(v->getName(),".Vsnd")!=NULL) 
+      c++;
+  if (c<1) return(-1);
+  printf(" channels: %i\n", c);
+
+  snd_init(c);  
+  vector **vcs = (vector **) calloc(c, sizeof(vector*));
+
+  int i=0;
+  for (vector * v = variables; v != NULL; v = (vector *) v->getNext ()) {
+    if (v->getDependencies () != NULL && len == v->getSize() && strstr(v->getName(),".Vsnd")!=NULL) {
+        vcs[i++]= v;
+      }
+  }
+  if (i != c) printf("Warning: segfault ahead..\n");
+
+  int ii;
+  for (ii = 0; ii < len; ii++) {
+    double ts= real(tme->get(ii)) * snd_get_samplerate();
+    for (i = 0; i < c; i++) {
+      double val = real(vcs[i]->get(ii));
+      snd_send(ts, i, val);
+    }
+  }
+  printf("closing snd out-file\n");
+  snd_close();
+  return(0);
+}
 /* Prints the given vector as independent dataset vector into the
    given file descriptor. */
 void dataset::printDependency (vector * v, FILE * f) {
diff --git a/src/dataset.h b/src/dataset.h
index 62a9359..dda01fc 100644
--- a/src/dataset.h
+++ b/src/dataset.h
@@ -53,6 +53,7 @@ class dataset : public object
   void printData (vector *, FILE *);
   void printDependency (vector *, FILE *);
   void printVariable (vector *, FILE *);
+  int printSndfile (void);
   vector * findDependency (char *);
   vector * findVariable (char *);
   vector * getDependencies (void) { return dependencies; }
diff --git a/src/input.cpp b/src/input.cpp
index c49d2f8..2b0db49 100644
--- a/src/input.cpp
+++ b/src/input.cpp
@@ -346,6 +346,8 @@ circuit * input::createCircuit (char * type) {
     return new vdc ();
   else if (!strcmp (type, "Idc"))
     return new idc ();
+  else if (!strcmp (type, "Vsnd"))
+    return new vsnd ();
   else if (!strcmp (type, "Vac"))
     return new vac ();
   else if (!strcmp (type, "Iac"))
@@ -479,6 +481,8 @@ analysis * input::createAnalysis (char * type) {
     return new parasweep ();
   else if (!strcmp (type, "AC"))
     return new acsolver ();
+  else if (!strcmp (type, "TSOUND"))
+    return new trsolver ();
   else if (!strcmp (type, "TR"))
     return new trsolver ();
   else if (!strcmp (type, "HB"))
diff --git a/src/qucsdefs.h b/src/qucsdefs.h
index 5e8c1a3..3d3331c 100644
--- a/src/qucsdefs.h
+++ b/src/qucsdefs.h
@@ -161,6 +161,18 @@ struct define_t qucs_definition_available[] =
     { { "I", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_NO_RANGE }, PROP_NO_PROP },
     { PROP_NO_PROP }
   },
+  /* Sound voltage source */
+  { "Vsnd", 2, PROP_COMPONENT, PROP_NO_SUBSTRATE, PROP_LINEAR,
+    { { "U", PROP_REAL, { 1.0, PROP_NO_STR }, PROP_NO_RANGE }, PROP_NO_PROP },
+    { { "Channel", PROP_INT, { 0.0, PROP_NO_STR }, PROP_POS_RANGE },
+      { "Oversampling", PROP_REAL, { 64.0, PROP_NO_STR }, PROP_MIN_VAL(1) },
+      { "TimeOffset", PROP_REAL, { 0.0, PROP_NO_STR }, PROP_NO_RANGE },
+      { "Samplerate", PROP_REAL, { 48000.0, PROP_NO_STR }, PROP_MIN_VAL(1) },
+      { "Uoffset", PROP_REAL, { 0.0, PROP_NO_STR }, PROP_NO_RANGE },
+      { "File", PROP_STR, { PROP_NO_VAL, "in.wav"}, PROP_NO_RANGE },
+      { "id", PROP_REAL, { 0.0, PROP_NO_STR }, PROP_POS_RANGE },
+      PROP_NO_PROP }
+  },
   /* AC voltage source */
   { "Vac", 2, PROP_COMPONENT, PROP_NO_SUBSTRATE, PROP_LINEAR,
     { { "U", PROP_REAL, { 1, PROP_NO_STR }, PROP_NO_RANGE }, PROP_NO_PROP },
@@ -1073,6 +1085,38 @@ struct define_t qucs_definition_available[] =
       { "initialDC", PROP_STR, { PROP_NO_VAL, "yes" }, PROP_NO_RANGE },
       PROP_NO_PROP }
   },
+  /* transient sound analysis */
+  { "TSOUND", 0, PROP_ACTION, PROP_NO_SUBSTRATE, PROP_LINEAR,
+    { { "Type", PROP_STR, { PROP_NO_VAL, "lin" }, PROP_NO_RANGE },
+      { "Start", PROP_REAL, { 0, PROP_NO_STR }, PROP_POS_RANGE },
+      { "Stop", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_POS_RANGE },
+      { "Points", PROP_INT, { 10, PROP_NO_STR }, PROP_MIN_VAL (2) },
+      PROP_NO_PROP },
+    { { "IntegrationMethod", PROP_STR, { PROP_NO_VAL, "Trapezoidal" },
+	PROP_NO_RANGE },
+      { "Order", PROP_INT, { 2, PROP_NO_STR }, { '[', 1, 6, ']' } },
+      { "InitialStep", PROP_REAL, { 1e-9, PROP_NO_STR }, PROP_POS_RANGE },
+      { "MinStep", PROP_REAL, { 1e-16, PROP_NO_STR }, PROP_POS_RANGE },
+      { "MaxStep", PROP_REAL, { 0, PROP_NO_STR }, PROP_POS_RANGE },
+      { "MaxIter", PROP_INT, { 150, PROP_NO_STR }, { '[', 2, 10000, ']' } },
+      { "abstol", PROP_REAL, { 1e-12, PROP_NO_STR }, PROP_RNG_X01I },
+      { "vntol", PROP_REAL, { 1e-6, PROP_NO_STR }, PROP_RNG_X01I },
+      { "reltol", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_RNG_X01I },
+      { "LTEabstol", PROP_REAL, { 1e-6, PROP_NO_STR }, PROP_RNG_X01I },
+      { "LTEreltol", PROP_REAL, { 1e-3, PROP_NO_STR }, PROP_RNG_X01I },
+      { "LTEfactor", PROP_REAL, { 1, PROP_NO_STR }, { '[', 1, 16, ']' } },
+      { "Temp", PROP_REAL, { 26.85, PROP_NO_STR }, PROP_MIN_VAL (K) },
+      { "Solver", PROP_STR, { PROP_NO_VAL, "CroutLU" }, PROP_NO_RANGE },
+      { "relaxTSR", PROP_STR, { PROP_NO_VAL, "no" }, PROP_NO_RANGE },
+      { "initialDC", PROP_STR, { PROP_NO_VAL, "yes" }, PROP_NO_RANGE },
+      { "File", PROP_STR, { PROP_NO_VAL, "out.wav"}, PROP_NO_RANGE },
+      { "Oversampling", PROP_INT, { 64, PROP_NO_STR }, PROP_MIN_VAL(1) },
+      { "Uoffset", PROP_REAL, { 0.0, PROP_NO_STR }, PROP_NO_RANGE },
+      { "Umult", PROP_REAL, { 1.0, PROP_NO_STR }, PROP_NO_RANGE },
+      { "Samplerate", PROP_INT, { 48000, PROP_NO_STR }, PROP_MIN_VAL(1) },
+      { "Format", PROP_STR, { PROP_NO_VAL, "wav24"}, PROP_NO_RANGE },
+      PROP_NO_PROP }
+  },
   /* harmonic balance analysis */
   { "HB", 0, PROP_ACTION, PROP_NO_SUBSTRATE, PROP_LINEAR,
     { { "n", PROP_INT, { 1, PROP_NO_STR }, PROP_MIN_VAL (1) },
diff --git a/src/sndprint.c b/src/sndprint.c
new file mode 100644
index 0000000..9c7d84a
--- /dev/null
+++ b/src/sndprint.c
@@ -0,0 +1,318 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <sndfile.h>
+#include <string.h>
+#include <math.h>
+#include <inttypes.h>
+#include <config.h>
+#include "sndprint.h"
+
+
+int o_samplerate = 48000;
+int o_sndfmt = (SF_FORMAT_WAV | SF_FORMAT_PCM_24);
+float o_mult = 1.0;
+float o_off = 0.0;
+
+//////////////////////////////////   aliki  //////////////////////////////////
+
+#define HDRSIZE 256
+
+void * my_open_aliki(char *fn, int nchannel) {
+  char p[HDRSIZE];
+  FILE	*aldfile;
+  if ((aldfile = fopen (fn, "w")) == 0) {
+    printf ("Error: Not able to open output file '%s'\n", fn);
+    exit (1);
+  }
+
+  strcpy (p, "aliki");
+  p [6] = p [7] = 0;
+  *(uint32_t *)(p +  8) = 2; //_vers
+  *(uint32_t *)(p + 12) = nchannel; // _type;
+  *(uint32_t *)(p + 16) = o_samplerate; //_rate_n;
+  *(uint32_t *)(p + 20) = 1; //_rate_d;
+  *(uint32_t *)(p + 24) = 486239; //_n_fram;
+  *(uint32_t *)(p + 28) = 1; // _n_sect;
+  *(uint32_t *)(p + 32) = 0; // _tref_i;
+  *(uint32_t *)(p + 36) = 0; // _tref_n;
+  *(uint32_t *)(p + 40) = 1; // _tref_d;
+  *(uint32_t *)(p + 44) = 0; // _bits;
+
+  memset (p + 48, 0, HDRSIZE - 48);
+  if (fwrite (p, 1, HDRSIZE, aldfile) != HDRSIZE) {
+    printf ("Error: Not able to write aliki header to '%s'\n", fn);
+    fclose (aldfile);
+    exit(1);
+  }
+  return ((void*) aldfile);
+}
+
+int my_write_aliki(void *d, float val) {
+  return(fwrite(&val, sizeof (float), 1, (FILE*) d));
+}
+
+void my_close_aliki(void *d) {
+  fclose((FILE*) d);
+}
+
+//////////////////////////////////  sndfile //////////////////////////////////
+
+typedef struct {
+  SNDFILE *outfile ;
+  int sf_channels;
+  int sf_bptr;
+  float *sf_buf;
+} SSFILE;
+
+void * my_open_sf(char *fn, int nchannel) {
+
+  SSFILE *d = calloc(1,sizeof(SSFILE));
+  SF_INFO sfinfo ;
+
+  sfinfo.samplerate = o_samplerate;
+  sfinfo.channels = nchannel;
+  sfinfo.frames = 0;
+  sfinfo.format = o_sndfmt;
+
+  d->sf_channels = nchannel;
+  d->sf_bptr = 0;
+  d->sf_buf=calloc(nchannel, sizeof(float));
+
+  if ((d->outfile = sf_open (fn, SFM_WRITE, &sfinfo)) == NULL) {
+    printf ("Error: Not able to open output file '%s'\n", fn);
+    exit (1) ;
+  }
+
+#if 1
+  sf_command (d->outfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) ;
+  sf_command (d->outfile, SFC_SET_CLIPPING, NULL, SF_TRUE) ;
+#endif
+
+  return ((void*)d);
+}
+
+int my_write_sf(void *d, float val) {
+  SSFILE *p= (SSFILE*) d;
+  p->sf_buf[p->sf_bptr++] =val;
+  if (p->sf_bptr >= p->sf_channels) {
+    sf_writef_float (p->outfile, p->sf_buf, 1);
+    p->sf_bptr=0;
+  }
+  return (1);
+}
+
+void my_close_sf(void *d) {
+  sf_close(((SSFILE*)d)->outfile);
+  //free(((SSFILE*)d)->sf_buf);
+  free((SSFILE*)d);
+}
+
+
+
+//////////////////////////////////   spice  //////////////////////////////////
+
+typedef struct SP_BUF {
+  double tme;
+  double *val;
+} SP_BUF;
+
+void (*p_close)(void*);
+void *(*p_open)(char*, int);
+int  (*p_write)(void*, float);
+void * outfile;
+uint32_t sample;
+int sp_nchannel;
+#define SP_MAX (2)
+SP_BUF *sp_buf;
+char *filename = NULL;
+
+#define HAVE_SRC
+
+#ifndef HAVE_SRC
+#define OVERSAMPLING (1.0)
+#else
+#include <samplerate.h>
+#define OBUFSIZE 256
+int oversampling = 8;
+#define OVERSAMPLING ((double) oversampling)
+SRC_STATE *sp_rabbit;
+int sp_rabbit_err;
+float *sp_interleaved; 
+float *sp_resampled; 
+int iptr = 0;
+
+int resample_wrapper (void *d, float val) {
+  sp_interleaved[iptr++] = val;
+  size_t ibufsize = sp_nchannel * OBUFSIZE * OVERSAMPLING;
+  size_t obufsize = sp_nchannel * OBUFSIZE ;
+  if (iptr ==  ibufsize) {
+
+    SRC_DATA src_data;
+    src_data.data_in = sp_interleaved;
+    src_data.data_out = sp_resampled;
+    src_data.input_frames  = iptr/sp_nchannel;
+    src_data.output_frames = OBUFSIZE;
+    src_data.end_of_input  = 0;
+    src_data.src_ratio     =  1.0/OVERSAMPLING;
+    src_data.input_frames_used = 0;
+    src_data.output_frames_gen = 0;
+  
+    //printf ("the rabbit says: %s\n", src_strerror(
+    src_process(sp_rabbit, &src_data);
+    //));
+
+    if (src_data.input_frames_used *sp_nchannel != iptr) {
+      printf ("resample warning: in: %li != %i\n", src_data.input_frames_used*sp_nchannel, iptr);
+    }
+
+    int i;
+    for (i=0; i< src_data.output_frames_gen*sp_nchannel; i++) 
+      p_write (d, sp_resampled[i]);
+
+    iptr=0;
+    if (src_data.output_frames_gen *sp_nchannel != obufsize) {
+      printf ("resample warning: out %li != %i\n", src_data.output_frames_gen*sp_nchannel,  obufsize);
+      return(-1);
+    }
+    return (src_data.output_frames_gen*sp_nchannel);
+  }
+  return (0);
+}
+
+#endif
+
+void snd_configure(char *fn, int srate, int fmt, double mult, double off, int os ){
+  if (filename) free(filename);
+  filename=strdup(fn);
+
+  o_samplerate = srate;
+  o_mult = mult;
+  o_off = off;
+  oversampling = os;
+  if (fmt!=0) {
+    p_close = &my_close_sf;
+    p_open = &my_open_sf;
+    p_write = &my_write_sf;
+    o_sndfmt=(fmt>0)?fmt:(SF_FORMAT_WAV | SF_FORMAT_PCM_24);
+    printf("info: opened snd file '%s'\n",filename);
+  } else {
+    p_close = &my_close_aliki;
+    p_open = &my_open_aliki;
+    p_write = &my_write_aliki;
+    printf("info: opened aliki file '%s'\n",filename);
+  }
+}
+
+int snd_format(char *fmt) {
+  int f = atoi(fmt);
+  if (!strcmp(fmt, "wav")) f= (SF_FORMAT_WAV | SF_FORMAT_PCM_24);
+  if (!strcmp(fmt, "wav16")) f= (SF_FORMAT_WAV | SF_FORMAT_PCM_16);
+  if (!strcmp(fmt, "wav24")) f= (SF_FORMAT_WAV | SF_FORMAT_PCM_24);
+  if (!strcmp(fmt, "wav32")) f= (SF_FORMAT_WAV | SF_FORMAT_PCM_32);
+  if (!strcmp(fmt, "aiff")) f= (SF_FORMAT_AIFF | SF_FORMAT_PCM_16);
+  if (!strcmp(fmt, "aliki")) f= 0;
+  return (f);
+}
+
+void snd_init(int nchannel) {
+  int i;
+  if (!filename) snd_configure("spice.wav", 48000.0, o_sndfmt, o_mult, o_off, oversampling);
+  outfile = p_open (filename, nchannel);
+  sp_nchannel = nchannel;
+  sp_buf = calloc(nchannel, sizeof(SP_BUF));
+  for (i=0; i< SP_MAX; i++){
+    sp_buf[i].tme=0.0;
+    sp_buf[i].val = calloc(nchannel, sizeof(float));
+  }
+  sample=0;
+#ifdef HAVE_SRC
+  sp_interleaved=calloc(nchannel*OBUFSIZE*OVERSAMPLING, sizeof(float));
+  sp_resampled=calloc(nchannel*OBUFSIZE, sizeof(float));
+  sp_rabbit=src_new(SRC_SINC_BEST_QUALITY, nchannel, &sp_rabbit_err);
+  src_set_ratio(sp_rabbit, 1.0/OVERSAMPLING);
+  src_reset(sp_rabbit);
+#endif
+}
+#define SND_DEBUG
+int snd_send(double tme, int c, double out) {
+  int i;
+  int rv =0;
+  if (c >= sp_nchannel) {
+    printf("ignored channel %i\n",c);
+    return(0);
+  }
+  if (c==0) for (i=SP_MAX-1; i>0; i--) {
+    memmove(&(sp_buf[i]), &(sp_buf[i-1]), sizeof(SP_BUF));
+  }
+  sp_buf[0].tme=tme * OVERSAMPLING;
+  sp_buf[0].val[c]=out;
+#ifdef SND_DEBUG
+  printf ("INFO : c:%i tme:%f fsmp:%i val:%f\n", c, tme, sample,out); 
+#endif
+
+  if (sample == 0) {
+    if (c==(sp_nchannel-1)) 
+      sample = ceil(tme * OVERSAMPLING);
+    return (0);
+  }
+
+  if ( (sample) < ceil(tme * OVERSAMPLING) ) {
+    if (!(sp_buf[0].tme > sample)) printf ("error 1 %f !> %i\n",sp_buf[0].tme,sample);
+    if ( (sp_buf[1].tme > sample)) printf ("error 2 %f !< %i\n",sp_buf[1].tme,sample);
+#if 0 // DEBUG
+    if ((sp_buf[0].tme - sample) > 1.0) printf ("error 3 large timestep: dv/dt=%e dt:%f dv:%e\n",
+      (sp_buf[0].val[c] - sp_buf[1].val[c]) / (sp_buf[0].tme - sample) ,
+      (sp_buf[0].tme - sample), ( sp_buf[0].val[c] - sp_buf[1].val[c]) );
+#endif
+
+    // linear
+    double p = (sp_buf[0].tme - sample ) / (sp_buf[0].tme - sp_buf[1].tme);
+    double val = sp_buf[0].val[c] - p * ( sp_buf[0].val[c] - sp_buf[1].val[c] );
+#ifdef SND_DEBUG
+    printf ("DEBUG: writing c:%i p:%f*[%f - %f] v:%f\n",c,p,sp_buf[0].val[c], sp_buf[1].val[c], val);
+#endif
+
+#ifdef HAVE_SRC
+    rv = resample_wrapper (outfile, o_off + val * o_mult);
+#else
+    p_write(outfile, o_off + val * o_mult);
+    if (c==(sp_nchannel-1)) rv =1;
+#endif
+    if (c==(sp_nchannel-1)) sample ++;
+
+  } else {
+#ifdef SND_DEBUG
+    printf(" ^^^^^^^^^ SKIPPED ^^^^^^^^^\n");
+#endif
+  }
+  return (rv);
+}
+
+void snd_close(void) {
+  printf("closing sndfile\n");
+#ifdef HAVE_SRC
+  while (!resample_wrapper(outfile, 0.0)); // flush buffer.
+#endif
+  p_close(outfile);
+  if (filename) free(filename); filename=NULL;
+#ifdef HAVE_SRC
+  free (sp_interleaved);
+  free (sp_resampled);
+#endif
+  /*
+  int i;
+  for (i=0; i< SP_MAX; i++){ 
+    free (sp_buf[i].val);
+    sp_buf[i].val=NULL;
+  }
+  */
+  free (sp_buf);
+}
+
+double snd_get_samplerate(void) {
+  return ((double) o_samplerate);
+}
+
+/* vi:set ts=8 sts=2 sw=2: */
+
diff --git a/src/sndprint.h b/src/sndprint.h
new file mode 100644
index 0000000..b9bfa3a
--- /dev/null
+++ b/src/sndprint.h
@@ -0,0 +1,11 @@
+#ifndef _SPICE_SNDFILE_H
+#define _SPICE_SNDFILE_H
+
+void snd_configure(char*, int, int, double, double, int);
+void snd_init(int);
+void snd_close(void);
+int snd_send(double, int, double);
+int snd_format(char*);
+double snd_get_samplerate(void);
+
+#endif
diff --git a/src/trsolver.cpp b/src/trsolver.cpp
index 7cb6d1e..f22fbd8 100644
--- a/src/trsolver.cpp
+++ b/src/trsolver.cpp
@@ -152,6 +152,10 @@ int trsolver::dcAnalysis (void) {
   return error;
 }
 
+extern "C" {
+#include "sndprint.h"
+}
+
 /* This is the transient netlist solver.  It prepares the circuit list
    for each requested time and solves it then. */
 void trsolver::solve (void) {
@@ -160,6 +164,16 @@ void trsolver::solve (void) {
   char * solver = getPropertyString ("Solver");
   relaxTSR = !strcmp (getPropertyString ("relaxTSR"), "yes") ? true : false;
   initialDC = !strcmp (getPropertyString ("initialDC"), "yes") ? true : false;
+  sndOut = getPropertyString ("File") ? true : false;
+
+  if (sndOut) {
+  	nr_double_t o = getPropertyDouble ("Uoffset");
+  	nr_double_t m = getPropertyDouble ("Umult");
+  	snd_configure(getPropertyString ("File"), 
+	    getPropertyInteger ("Samplerate"), 
+	    snd_format(getPropertyString("Format")), m, o,
+	    getPropertyInteger ("Oversampling"));
+  }
 
   runs++;
   saveCurrent = current = 0;
@@ -736,7 +750,9 @@ void trsolver::saveAllResults (nr_double_t time) {
     data->addDependency (t);
   }
   if (runs == 1) t->add (time);
-  saveResults ("Vt", "It", 0, t);
+  if (sndOut) saveResults ("Vsnd", "It", 0, t);
+  else saveResults ("Vt", "It", 0, t);
+  
 }
 
 /* This function is meant to adapt the current time-step the transient
diff --git a/src/trsolver.h b/src/trsolver.h
index 43fd604..b851100 100644
--- a/src/trsolver.h
+++ b/src/trsolver.h
@@ -97,6 +97,7 @@ class trsolver : public nasolver<nr_double_t>, public states<nr_double_t>
   history * tHistory;
   bool relaxTSR;
   bool initialDC;
+  bool sndOut;
 };
 
 #endif /* __TRSOLVER_H__ */
