added possibility to save the encoded stream to a local file only

(no streaming server needed)
This commit is contained in:
darkeye 2002-02-28 09:49:25 +00:00
parent 2771fbf1d3
commit 84cee897f7
9 changed files with 612 additions and 22 deletions

View File

@ -1,3 +1,8 @@
DarkIce 0.9
o added possibility to simply read from the soundcard, encode, and
save the encoded data into a local file (no streaming server needed)
20-02-2002: DarkIce 0.8 released
o added possibility to disable lowpass and highpass filtering for lame

View File

@ -1,6 +1,6 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT(src/DarkIce.cpp)
AM_INIT_AUTOMAKE(darkice, 0.8)
AM_INIT_AUTOMAKE(darkice, 0.9beta)
AM_CONFIG_HEADER(config.h)

View File

@ -1,4 +1,4 @@
.TH darkice.cfg 5 "February 20, 2002" "DarkIce" "DarkIce live audio streamer"
.TH darkice.cfg 5 "February 28, 2002" "DarkIce" "DarkIce live audio streamer"
.SH NAME
darkice.cfg \- configuration file for darkice
.SH DESCRIPTION
@ -27,11 +27,12 @@ configuration file contains the following sections:
[icecast-0] ... [icecast-7]
[icecast2-0] ... [icecast2-7]
[shoutcast-0] ... [shoutcast-7]
[file-0] ... [file-7]
.fi
The order of the sections is not important. Sections [general] and [input]
are required, and at least one of [icecast-x], [icecast2-x]
or [shoutcast-x] is needed.
are required, and at least one of [icecast-x], [icecast2-x], [shoutcast-x]
or [file-x] is needed.
In particular, the following sections and values are recognized:
.PP
@ -154,8 +155,7 @@ disabled.
This section describes an output to an
.B IceCast2
server, while encoding
with the ogg vobis encoder.
server, while encoding with the ogg vobis encoder.
There may be at most 8 outputs, numbered from 0 ... 7.
The number is included in the section name (e.g. [icecast2-0] ... [icecast2-7]).
The stream will be reachable at
@ -287,6 +287,47 @@ Dump the same mp3 data sent to the
.B ShoutCast
server to this local file.
.PP
.B [file-x]
This section describes an output to a local file in either Ogg Vorbis or
mp3 format.
There may be at most 8 outputs, numbered from 0 ... 7.
The number is included in the section name (e.g. [file-0] ... [file-7]).
Required values:
.TP
.I format
Format to encode in. Must be either 'mp3' or 'vorbis'.
.TP
.I bitrate
Bit rate to encode to in kBits / sec (e.g. 96)
.TP
.I fileName
The name of the local file to save the encoded data into.
.PP
Optional values:
.TP
.I sampleRate
The sample rate of the encoded mp3 output. If not specified, defaults
to the value of the input sample rate.
Only used if the output format is mp3.
.TP
.I lowpass
Lowpass filter setting for the lame encoder. If not set or set to 0,
the encoder's default behaviour is used. If set to -1, the filter is
disabled.
Only used if the output format is mp3.
.TP
.I highpass
Highpass filter setting for the lame encoder. If not set or set to 0,
the encoder's default behaviour is used. If set to -1, the filter is
disabled.
Only used if the output format is mp3.
.PP
A sample configuration file follows. This file makes
.B DarkIce
@ -336,6 +377,29 @@ localDumpFile = /tmp/encoder-dump.mp3
.fi
.PP
The following sample configuration file simply encodes the 16 bit stereo
44.1 kHz sound card input into Ogg Vorbis at 96 kb/s for 60 seconds, and saves
it in the local file at /tmp/save.ogg.
.nf
[general]
duration = 60
bufferSecs = 5
[input]
device = /dev/dsp
sampleRate = 44100
bitsPerSample = 16
channel = 2
[file-0]
format = vorbis
bitrate = 96
fileName = /tmp/save.ogg
.fi
.PP
A bit more complicated sample follows. This one makes
.B DarkIce

View File

@ -67,7 +67,7 @@ CastSink :: init ( TcpSocket * socket,
{
this->socket = socket;
this->streamDump = streamDump;
this->password = Util::strDup( password);
this->password = password ? Util::strDup( password) : 0;
this->bitRate = bitRate;
this->name = name ? Util::strDup( name) : 0;
this->url = url ? Util::strDup( url) : 0;
@ -75,8 +75,9 @@ CastSink :: init ( TcpSocket * socket,
this->isPublic = isPublic;
this->bufferDuration = bufferDuration;
bufferedSink = new BufferedSink( socket,
(bitRate * 1024 / 8) * bufferDuration);
bufferedSink = socket ? new BufferedSink( socket,
(bitRate * 1024 / 8) * bufferDuration)
: 0;
}
@ -91,7 +92,9 @@ CastSink :: strip ( void ) throw ( Exception )
close();
}
if ( password ) {
delete[] password;
}
if ( name ) {
delete[] name;
}
@ -141,6 +144,10 @@ CastSink :: open ( void ) throw ( Exception )
$Source$
$Log$
Revision 1.7 2002/02/28 09:49:25 darkeye
added possibility to save the encoded stream to a local file only
(no streaming server needed)
Revision 1.6 2002/02/20 11:54:11 darkeye
added local dump file possibility

View File

@ -76,7 +76,7 @@
#include "IceCast.h"
#include "IceCast2.h"
#include "ShoutCast.h"
#include "FileSink.h"
#include "FileCast.h"
#include "DarkIce.h"
#ifdef HAVE_LAME_LIB
@ -163,6 +163,7 @@ DarkIce :: init ( const Config & config ) throw ( Exception )
configIceCast( config, bufferSecs);
configIceCast2( config, bufferSecs);
configShoutCast( config, bufferSecs);
configFileCast( config);
}
@ -180,11 +181,11 @@ DarkIce :: configIceCast ( const Config & config,
size_t streamLen = Util::strLen( stream);
unsigned int u;
for ( u = 0; u < maxOutput; ++u ) {
for ( u = noAudioOuts; u < maxOutput; ++u ) {
const ConfigSection * cs;
// ugly hack to change the section name to "stream0", "stream1", etc.
stream[streamLen-1] = '0' + u;
stream[streamLen-1] = '0' + (u - noAudioOuts);
if ( !(cs = config.get( stream)) ) {
break;
@ -305,11 +306,11 @@ DarkIce :: configIceCast2 ( const Config & config,
size_t streamLen = Util::strLen( stream);
unsigned int u;
for ( u = 0; u < maxOutput; ++u ) {
for ( u = noAudioOuts; u < maxOutput; ++u ) {
const ConfigSection * cs;
// ugly hack to change the section name to "stream0", "stream1", etc.
stream[streamLen-1] = '0' + u;
stream[streamLen-1] = '0' + (u - noAudioOuts);
if ( !(cs = config.get( stream)) ) {
break;
@ -456,11 +457,11 @@ DarkIce :: configShoutCast ( const Config & config,
size_t streamLen = Util::strLen( stream);
unsigned int u;
for ( u = 0; u < maxOutput; ++u ) {
for ( u = noAudioOuts; u < maxOutput; ++u ) {
const ConfigSection * cs;
// ugly hack to change the section name to "stream0", "stream1", etc.
stream[streamLen-1] = '0' + u;
stream[streamLen-1] = '0' + (u - noAudioOuts);
if ( !(cs = config.get( stream)) ) {
break;
@ -565,6 +566,113 @@ DarkIce :: configShoutCast ( const Config & config,
}
/*------------------------------------------------------------------------------
* Look for the FileCast stream outputs in the config file
*----------------------------------------------------------------------------*/
void
DarkIce :: configFileCast ( const Config & config )
throw ( Exception )
{
// look for FileCast encoder output streams,
// sections [file-0], [file-1], ...
char stream[] = "file- ";
size_t streamLen = Util::strLen( stream);
unsigned int u;
for ( u = noAudioOuts; u < maxOutput; ++u ) {
const ConfigSection * cs;
// ugly hack to change the section name to "stream0", "stream1", etc.
stream[streamLen-1] = '0' + (u - noAudioOuts);
if ( !(cs = config.get( stream)) ) {
break;
}
const char * str;
const char * format = 0;
unsigned int bitrate = 0;
const char * targetFileName = 0;
unsigned int sampleRate = 0;
int lowpass = 0;
int highpass = 0;
format = cs->getForSure( "format", " missing in section ", stream);
if ( !Util::strEq( format, "vorbis") && !Util::strEq( format, "mp3") ) {
throw Exception( __FILE__, __LINE__,
"unsupported stream format: ", format);
}
str = cs->getForSure("bitrate", " missing in section ", stream);
bitrate = Util::strToL( str);
targetFileName = cs->getForSure( "fileName",
" missing in section ",
stream);
str = cs->get( "sampleRate");
sampleRate = str ? Util::strToL( str) : dsp->getSampleRate();
str = cs->get( "lowpass");
lowpass = str ? Util::strToL( str) : 0;
str = cs->get( "highpass");
highpass = str ? Util::strToL( str) : 0;
// go on and create the things
// the underlying file
FileSink * targetFile = new FileSink( targetFileName);
if ( !targetFile->exists() ) {
if ( !targetFile->create() ) {
throw Exception( __FILE__, __LINE__,
"can't create output file", targetFileName);
}
}
// streaming related stuff
audioOuts[u].socket = 0;
audioOuts[u].server = new FileCast( targetFile );
if ( Util::strEq( format, "mp3") ) {
#ifndef HAVE_LAME_LIB
throw Exception( __FILE__, __LINE__,
"DarkIce not compiled with lame support, "
"thus can't create mp3 stream: ",
stream);
#else
audioOuts[u].encoder = new LameLibEncoder(
audioOuts[u].server.get(),
dsp.get(),
bitrate,
sampleRate,
dsp->getChannel(),
lowpass,
highpass );
#endif // HAVE_LAME_LIB
} else if ( Util::strEq( format, "vorbis") ) {
#ifndef HAVE_VORBIS_LIB
throw Exception( __FILE__, __LINE__,
"DarkIce not compiled with Ogg Vorbis support, "
"thus can't Ogg Vorbis stream: ",
stream);
#else
audioOuts[u].encoder = new VorbisLibEncoder(
audioOuts[u].server.get(),
dsp.get(),
bitrate,
dsp->getSampleRate(),
dsp->getChannel() );
#endif // HAVE_VORBIS_LIB
} else {
throw Exception( __FILE__, __LINE__,
"Illegal stream format: ", format);
}
encConnector->attach( audioOuts[u].encoder.get());
}
noAudioOuts += u;
}
/*------------------------------------------------------------------------------
* Set POSIX real-time scheduling, if super-user
*----------------------------------------------------------------------------*/
@ -697,6 +805,10 @@ DarkIce :: run ( void ) throw ( Exception )
$Source$
$Log$
Revision 1.25 2002/02/28 09:49:25 darkeye
added possibility to save the encoded stream to a local file only
(no streaming server needed)
Revision 1.24 2002/02/20 11:54:11 darkeye
added local dump file possibility

View File

@ -80,9 +80,10 @@ class DarkIce : public virtual Referable, public virtual Reporter
private:
/**
* The maximum number of supported outputs.
* The maximum number of supported outputs. This should be
* <supported output types> * <outputs per type>
*/
static const unsigned int maxOutput = 24;
static const unsigned int maxOutput = 4 * 7;
/**
* Type describing each lame library output.
@ -144,6 +145,7 @@ class DarkIce : public virtual Referable, public virtual Reporter
*
* @param config the config Object to read initialization
* information from.
* @param bufferSecs number of seconds to buffer audio for
* @exception Exception
*/
void
@ -156,6 +158,7 @@ class DarkIce : public virtual Referable, public virtual Reporter
*
* @param config the config Object to read initialization
* information from.
* @param bufferSecs number of seconds to buffer audio for
* @exception Exception
*/
void
@ -168,12 +171,25 @@ class DarkIce : public virtual Referable, public virtual Reporter
*
* @param config the config Object to read initialization
* information from.
* @param bufferSecs number of seconds to buffer audio for
* @exception Exception
*/
void
configShoutCast ( const Config & config,
unsigned int bufferSecs ) throw ( Exception );
/**
* Look for file outputs from the config file.
* Called from init()
*
* @param config the config Object to read initialization
* information from.
* @exception Exception
*/
void
configFileCast ( const Config & config )
throw ( Exception );
/**
* Set POSIX real-time scheduling for the encoding process,
* if user permissions enable it.
@ -293,6 +309,10 @@ class DarkIce : public virtual Referable, public virtual Reporter
$Source$
$Log$
Revision 1.13 2002/02/28 09:49:25 darkeye
added possibility to save the encoded stream to a local file only
(no streaming server needed)
Revision 1.12 2001/09/14 19:31:06 darkeye
added IceCast2 / vorbis support

View File

@ -0,0 +1,103 @@
/*------------------------------------------------------------------------------
Copyright (c) 2000 Tyrell Corporation. All rights reserved.
Tyrell DarkIce
File : FileCast.cpp
Version : $Revision$
Author : $Author$
Location : $Source$
Copyright notice:
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
------------------------------------------------------------------------------*/
/* ============================================================ include files */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_STDIO_H
#include <stdio.h>
#else
#error need stdio.h
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#else
#error need string.h
#endif
#include "Exception.h"
#include "Source.h"
#include "Sink.h"
#include "Util.h"
#include "FileCast.h"
/* =================================================== local data structures */
/* ================================================ local constants & macros */
/*------------------------------------------------------------------------------
* File identity
*----------------------------------------------------------------------------*/
static const char fileid[] = "$Id$";
/* =============================================== local function prototypes */
/* ============================================================= module code */
/*------------------------------------------------------------------------------
* Open the connection
*----------------------------------------------------------------------------*/
bool
FileCast :: open ( void ) throw ( Exception )
{
if ( isOpen() ) {
return false;
}
if ( !targetFile->open() ) {
return false;
}
return true;
}
/*------------------------------------------------------------------------------
$Source$
$Log$
Revision 1.1 2002/02/28 09:49:25 darkeye
added possibility to save the encoded stream to a local file only
(no streaming server needed)
------------------------------------------------------------------------------*/

View File

@ -0,0 +1,277 @@
/*------------------------------------------------------------------------------
Copyright (c) 2000 Tyrell Corporation. All rights reserved.
Tyrell DarkIce
File : FileCast.h
Version : $Revision$
Author : $Author$
Location : $Source$
Copyright notice:
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
------------------------------------------------------------------------------*/
#ifndef FILE_CAST_H
#define FILE_CAST_H
#ifndef __cplusplus
#error This is a C++ include file
#endif
/* ============================================================ include files */
#include "Ref.h"
#include "Sink.h"
#include "CastSink.h"
#include "FileSink.h"
#include "FileCast.h"
/* ================================================================ constants */
/* =================================================================== macros */
/* =============================================================== data types */
/**
* Class representing output to a local file.
*
* @author $Author$
* @version $Revision$
*/
class FileCast : public CastSink
{
private:
/**
* The file to send the encoded data to.
*/
Ref<FileSink> targetFile;
/**
* Initalize the object.
*
* @param targetFile the file to send the encoded data to.
* @exception Exception
*/
inline void
init ( FileSink * targetFile )
throw ( Exception )
{
this->targetFile = targetFile;
}
/**
* De-initalize the object.
*
* @exception Exception
*/
inline void
strip ( void ) throw ( Exception )
{
if ( isOpen() ) {
close();
}
}
protected:
/**
* Default constructor. Always throws an Exception.
*
* @exception Exception
*/
inline
FileCast ( void ) throw ( Exception )
{
throw Exception( __FILE__, __LINE__);
}
/**
* Log in to the server using the socket avialable.
* No need to log in to a file.
*
* @return true if login was successful, false otherwise.
* @exception Exception
*/
inline virtual bool
sendLogin ( void ) throw ( Exception )
{
return true;
}
public:
/**
* Constructor.
*
* @param targetFile the file to send all the data to.
* @exception Exception
*/
inline
FileCast ( FileSink * targetFile )
throw ( Exception )
: CastSink( 0, 0, 0)
{
init( targetFile );
}
/**
* Copy constructor.
*
* @param cs the FileCast to copy.
*/
inline
FileCast( const FileCast & cs ) throw ( Exception )
{
init( targetFile.get() );
}
/**
* Destructor.
*
* @exception Exception
*/
inline virtual
~FileCast( void ) throw ( Exception )
{
strip();
}
/**
* Assignment operator.
*
* @param cs the FileCast to assign this to.
* @return a reference to this FileCast.
* @exception Exception
*/
inline virtual FileCast &
operator= ( const FileCast & cs ) throw ( Exception )
{
if ( this != &cs ) {
strip();
init( targetFile.get() );
}
return *this;
}
/**
* Open the FileCast.
*
* @return true if opening was successfull, false otherwise.
* @exception Exception
*/
virtual bool
open ( void ) throw ( Exception );
/**
* Check if the FileCast is open.
*
* @return true if the FileCast is open, false otherwise.
*/
inline virtual bool
isOpen ( void ) const throw ()
{
return targetFile->isOpen();
}
/**
* Check if the FileCast is ready to accept data.
* Blocks until the specified time for data to be available.
*
* @param sec the maximum seconds to block.
* @param usec micro seconds to block after the full seconds.
* @return true if the FileCast is ready to accept data,
* false otherwise.
* @exception Exception
*/
inline virtual bool
canWrite ( unsigned int sec,
unsigned int usec ) throw ( Exception )
{
return targetFile->canWrite( sec, usec);
}
/**
* Write data to the FileCast.
*
* @param buf the data to write.
* @param len number of bytes to write from buf.
* @return the number of bytes written (may be less than len).
* @exception Exception
*/
inline virtual unsigned int
write ( const void * buf,
unsigned int len ) throw ( Exception )
{
return targetFile->write( buf, len);
}
/**
* Flush all data that was written to the FileCast to the server.
*
* @exception Exception
*/
inline virtual void
flush ( void ) throw ( Exception )
{
return targetFile->flush();
}
/**
* Close the FileCast.
*
* @exception Exception
*/
inline virtual void
close ( void ) throw ( Exception )
{
return targetFile->close();
}
};
/* ================================================= external data structures */
/* ====================================================== function prototypes */
#endif /* FILE_CAST_H */
/*------------------------------------------------------------------------------
$Source$
$Log$
Revision 1.1 2002/02/28 09:49:25 darkeye
added possibility to save the encoded stream to a local file only
(no streaming server needed)
------------------------------------------------------------------------------*/

View File

@ -23,6 +23,8 @@ darkice_SOURCES = AudioEncoder.h\
IceCast2.h\
ShoutCast.cpp\
ShoutCast.h\
FileCast.h\
FileCast.cpp\
LameLibEncoder.cpp\
LameLibEncoder.h\
VorbisLibEncoder.cpp\