You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdemultimedia/arts/modules/synth/synth_capture_wav_impl.cpp

170 lines
4.1 KiB

/*
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);
}