summaryrefslogtreecommitdiffstats
path: root/arts/modules/synth/synth_capture_wav_impl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'arts/modules/synth/synth_capture_wav_impl.cpp')
-rw-r--r--arts/modules/synth/synth_capture_wav_impl.cpp169
1 files changed, 169 insertions, 0 deletions
diff --git a/arts/modules/synth/synth_capture_wav_impl.cpp b/arts/modules/synth/synth_capture_wav_impl.cpp
new file mode 100644
index 00000000..84e91648
--- /dev/null
+++ b/arts/modules/synth/synth_capture_wav_impl.cpp
@@ -0,0 +1,169 @@
+ /*
+
+ Copyright (C) 2000, 2001 Stefan Westerfeld
+ stefan@space.twc.de, Matthias Kretz <kretz@kde.org>
+
+ This program 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 of the License, or
+ (at your option) any later version.
+
+ This program 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 program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ */
+
+#include "artsmodulessynth.h"
+#include "convert.h"
+#include "mcoputils.h"
+#include "stdsynthmodule.h"
+#include "debug.h"
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+
+using namespace std;
+namespace Arts {
+
+class Synth_CAPTURE_WAV_impl :virtual public Synth_CAPTURE_WAV_skel,
+ virtual public StdSynthModule
+{
+ bool audioinit, scaleerr, running;
+ int audiofd, byteorder, v,datalen,channels;
+
+ unsigned char *outblock;
+ unsigned long maxsamples;
+
+ string _filename;
+
+/****
+
+ WAV writing code and header taken from kwave. Many thanks go to
+ Martin Wilz who has written this ;)
+
+ ****/
+
+ struct wavheader
+ {
+ char riffid[4];
+ long filelength;
+ char wavid[4];
+ char fmtid[4];
+ long fmtlength;
+ short int mode;
+ short int channels;
+ long rate;
+ long AvgBytesPerSec;
+ short int BlockAlign;
+ short int bitspersample;
+ } header;
+
+public:
+ Synth_CAPTURE_WAV_impl();
+ void streamInit();
+ void calculateBlock(unsigned long samples);
+ void streamEnd();
+ string filename() { return _filename; }
+ void filename( const string &newFilename );
+};
+
+Synth_CAPTURE_WAV_impl::Synth_CAPTURE_WAV_impl()
+ : running(false), _filename( "capture" )
+{
+}
+
+void Synth_CAPTURE_WAV_impl::streamInit()
+{
+ /*
+ * we use createFilePath to prevent the usual symlink security issues
+ * in /tmp - add .wav manually as createFilePath substitutes . with _
+ */
+ string filename = MCOPUtils::createFilePath(_filename)+ ".wav";
+ audiofd = open(filename.c_str(),O_WRONLY|O_CREAT|O_TRUNC,0644);
+
+/* write header */
+
+ int rate=44100;
+ int bit=16;
+
+ channels = 2; /* hardcoded here - make it a parameter? */
+
+ arts_info("capturing output to %s", filename.c_str());
+ datalen=0;
+
+ strncpy (header.riffid,"RIFF",4);
+ strncpy (header.wavid,"WAVE",4);
+ strncpy (header.fmtid,"fmt ",4);
+ header.fmtlength=16;
+ header.filelength=sizeof(struct wavheader);
+ header.mode=1;
+ header.channels=channels;
+ header.rate=rate;
+ header.AvgBytesPerSec=rate*bit/8;
+ header.BlockAlign=channels*bit/8;
+ header.bitspersample=bit;
+
+ write(audiofd,&header,sizeof (struct wavheader));
+ write(audiofd,"data",4);
+ write(audiofd,&datalen,4);
+
+ maxsamples = 0;
+ outblock = 0;
+ v = 0;
+ running = true;
+}
+
+void Synth_CAPTURE_WAV_impl::calculateBlock(unsigned long samples)
+{
+ if(samples > maxsamples)
+ {
+ maxsamples = samples;
+ outblock = (unsigned char *)realloc(outblock, maxsamples * 4);
+ // 2 channels, 16 bit
+ }
+
+ if(channels == 1)
+ convert_mono_float_16le(samples,left,outblock);
+
+ if(channels == 2)
+ convert_stereo_2float_i16le(samples,left,right,outblock);
+
+ write(audiofd,outblock,samples*channels*2);
+ datalen += samples*channels*2;
+}
+
+void Synth_CAPTURE_WAV_impl::streamEnd()
+{
+/* rewrite header which now contains the correct size of the file */
+ lseek(audiofd,0,SEEK_SET);
+ header.filelength=sizeof(struct wavheader)+datalen;
+ write(audiofd,&header,sizeof (struct wavheader));
+ write(audiofd,"data",4);
+ write(audiofd,&datalen,4);
+
+ close(audiofd);
+
+ running = false;
+}
+void Synth_CAPTURE_WAV_impl::filename( const string &newFilename )
+{
+ if(_filename != newFilename) {
+ _filename = newFilename;
+ if(running)
+ {
+ streamEnd();
+ streamInit();
+ }
+ filename_changed(newFilename);
+ }
+}
+
+REGISTER_IMPLEMENTATION(Synth_CAPTURE_WAV_impl);
+
+}