added singerbot plugin

git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@452 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
Javier Serrano Polo
2007-01-20 14:24:27 +00:00
parent 03a5e5df89
commit 56eead9a65
23 changed files with 801 additions and 42 deletions

View File

@@ -1,3 +1,54 @@
2007-01-20 Javier Serrano Polo <jasp00/at/terra/dot/es>
* plugins/singerbot/artwork.png:
* plugins/singerbot/logo.png:
* plugins/singerbot/Makefile.am:
* plugins/singerbot/singerbot.h:
* plugins/singerbot/singerbot.cpp:
initial release, SingerBot (experimental) instrument plugin
* configure.in:
* include/note_play_handle.h:
* plugins/Makefile.am:
* src/core/arp_and_chords_tab_widget.cpp:
* src/core/note_play_handle.cpp:
* src/tracks/instrument_track.cpp:
added singerbot support
* include/sample_buffer.h:
deleteResampling methods made static
* plugins/audio_file_processor/audio_file_processor.cpp:
* plugins/organic/organic.cpp:
* plugins/triple_oscillator/triple_oscillator.cpp:
* src/core/note_play_handle.cpp:
* src/tracks/instrument_track.cpp:
call deleteNotePluginData() only if there is plugin data, fixes
unprotected instruments
* plugins/vestige/vestige.cpp:
trigger deleteNotePluginData()
* src/tracks/instrument_track.cpp:
avoid double unlock
* configure.in:
fixed configuring with --with-stk
* acinclude.m4:
moved QT_TRANSLATIONS_DIR to config.h
* plugins/flp_import/flp_import.cpp:
* plugins/flp_import/unrtf/word.c:
optimized unsafe loops
* src/lib/sample_buffer.cpp:
* src/widgets/project_notes.cpp:
minor cosmetic changes
* include/shared_object.h:
not really thread-safe, will be removed
2007-01-02 Tobias Doerffel <tobydox/at/users/dot/sourceforge/dot/net>
* src/core/note.cpp:

View File

@@ -61,6 +61,7 @@ esac
AC_MSG_RESULT([$QT_VER ($QT_MAJOR)])
# Search for available Qt translations
AH_TEMPLATE(QT_TRANSLATIONS_DIR, [Define to Qt translations directory])
AC_MSG_CHECKING([Qt translations])
case "${QT_VER}" in
3*)
@@ -77,6 +78,8 @@ for i in $QT_TRANSLATIONS_SEARCH ; do
done
if test x"$QT_TRANSLATIONS" = x ; then
AC_MSG_WARN([*** not found! You may want to install a Qt i18n package])
else
AC_DEFINE_UNQUOTED(QT_TRANSLATIONS_DIR, "$QT_TRANSLATIONS")
fi
AC_MSG_RESULT([$QT_TRANSLATIONS])
@@ -273,10 +276,6 @@ if test x"$QT_IS_MT" = "xyes" ; then
QT_LIBS="$QT_LIBS"
fi
if test x"$QT_TRANSLATIONS" != x ; then
QT_CXXFLAGS="$QT_CXXFLAGS -DQT_TRANSLATIONS_DIR='\"$QT_TRANSLATIONS\"'"
fi
QT_LDADD="-L$QTDIR/lib $QT_LIBS"
#if test x$QT_IS_STATIC = xyes ; then

View File

@@ -2,8 +2,8 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.50)
AC_INIT(lmms, 0.2.1-svn20061228, lmms-devel/at/lists/dot/sf/dot/net)
AM_INIT_AUTOMAKE(lmms, 0.2.1-svn20061228)
AC_INIT(lmms, 0.2.1-svn20070120, lmms-devel/at/lists/dot/sf/dot/net)
AM_INIT_AUTOMAKE(lmms, 0.2.1-svn20070120)
AM_CONFIG_HEADER(config.h)
@@ -264,8 +264,8 @@ AM_CONDITIONAL(LADSPA_SUPPORT, test "$build_linux" = "true" )
# check for STK
AC_LANG_PUSH(C++)
AC_ARG_WITH(stk,
AS_HELP_STRING([--without-stk], [disable support for STK plugins]),
[ with_stk=no ], [ with_stk=yes ])
AS_HELP_STRING([--without-stk], [disable support for STK plugins]), ,
[ with_stk=yes ])
AH_TEMPLATE(HAVE_STK_H, [Define to 1 if you have the <stk/Stk.h> header file.])
if test "x$with_stk" = "xyes" ; then
AC_CHECK_HEADER([stk/Stk.h], HAVE_STK_H="true")
@@ -281,6 +281,29 @@ AM_CONDITIONAL(STK_SUPPORT, test ! -z "$HAVE_STK_H")
AC_LANG_POP(C++)
# check for Festival
AC_LANG_PUSH(C++)
AC_ARG_WITH(singerbot,
AS_HELP_STRING([--without-singerbot],
[disable support for SingerBot plugin]), ,
[ with_singerbot=yes ])
AH_TEMPLATE(SINGERBOT_SUPPORT,
[Define to 1 to enable SingerBot plugin support.])
if test "x$with_singerbot" = "xyes" ; then
ORIG_CPPFLAGS=$CPPFLAGS
CPPFLAGS+=" -I/usr/include/festival -I/usr/include/speech_tools"
CPPFLAGS+=" -Wno-non-template-friend"
AC_CHECK_HEADER([festival.h], FESTIVAL_SUPPORT="true")
AC_CHECK_LIB([Festival], [main], , FESTIVAL_SUPPORT="")
CPPFLAGS=$ORIG_CPPFLAGS
fi
if test ! -z "$FESTIVAL_SUPPORT" ; then
AC_DEFINE(SINGERBOT_SUPPORT)
fi
AM_CONDITIONAL(SINGERBOT_SUPPORT, test ! -z "$FESTIVAL_SUPPORT")
AC_LANG_POP(C++)
# check for vorbis-lib
AC_ARG_WITH(vorbis,
AS_HELP_STRING([--without-vorbis],
@@ -565,6 +588,7 @@ AC_CONFIG_FILES([Makefile
plugins/midi_import/Makefile
plugins/organic/Makefile
plugins/plucked_string_synth/Makefile
plugins/singerbot/Makefile
plugins/stk/Makefile
plugins/stk/mallets/Makefile
plugins/triple_oscillator/Makefile
@@ -756,6 +780,27 @@ else
fi
if test -z "$FESTIVAL_SUPPORT" ; then
if test "x$with_singerbot" = "xyes" ; then
echo " ========================"
echo " === LMMS - WARNING ======================================================="
echo " ========================"
echo " ="
echo " = You don't seem to have Festival development files."
echo " = The SingerBot instrument plugin will be ignored."
echo " = Before enabling this plugin, bear in mind that it is still experimental."
echo " ="
echo " = To remove this warning, please pass"
echo " = "
echo " = --without-singerbot"
echo " ="
with_warnings="true"
fi
else
PLUGINS_TO_BUILD="$PLUGINS_TO_BUILD\n\t\* SingerBot instrument plugin"
fi
if test -z "$HAVE_SAMPLERATE_H" ; then
echo " ========================"
echo " === LMMS - WARNING ======================================================="

View File

@@ -2,7 +2,7 @@
* note_play_handle.h - declaration of class notePlayHandle which is needed
* by LMMS-Play-Engine
*
* Copyright (c) 2004-2006 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2004-2007 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
@@ -207,6 +207,18 @@ public:
m_instrumentTrack->m_instrument->waitForWorkerThread();
}
#if SINGERBOT_SUPPORT
int patternIndex( void )
{
return( m_patternIndex );
}
void setPatternIndex( int _i )
{
m_patternIndex = _i;
}
#endif
private:
instrumentTrack * m_instrumentTrack; // needed for calling
@@ -232,6 +244,9 @@ private:
// sub-note)
bool m_muted; // indicates whether note is muted
bbTrack * m_bbTrack; // related BB track
#if SINGERBOT_SUPPORT
int m_patternIndex; // position among relevant notes
#endif
private slots:

View File

@@ -1,7 +1,7 @@
/*
* sample_buffer.h - container-class sampleBuffer
*
* Copyright (c) 2005-2006 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2005-2007 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
@@ -130,7 +130,7 @@ public:
return( m_data );
}
void FASTCALL deleteResamplingData( void * * _ptr );
static void FASTCALL deleteResamplingData( void * * _ptr );
QString openAudioFile( void ) const;
@@ -232,7 +232,7 @@ private:
void initResampling( void );
void quitResampling( void );
SRC_STATE * createResamplingContext( void );
void FASTCALL destroyResamplingContext( SRC_STATE * _context );
static void FASTCALL destroyResamplingContext( SRC_STATE * _context );
SRC_DATA m_srcData;
SRC_STATE * m_srcState;

View File

@@ -50,6 +50,7 @@ public:
template<class T>
static T * ref( T * _object )
{
// TODO: Use QShared
_object->m_reference_mutex.lock();
++_object->m_reference_count;
_object->m_reference_mutex.unlock();

View File

@@ -10,6 +10,10 @@ if STK_SUPPORT
STK_DIR=stk
endif
if SINGERBOT_SUPPORT
SINGERBOT_DIR=singerbot
endif
SUBDIRS = \
audio_file_processor \
bass_booster \
@@ -21,6 +25,7 @@ SUBDIRS = \
midi_import \
organic \
plucked_string_synth \
$(SINGERBOT_DIR) \
$(STK_DIR) \
triple_oscillator \
$(VST_DIRS) \

View File

@@ -1,7 +1,7 @@
/*
* audio_file_processor.cpp - instrument for using audio-files
*
* Copyright (c) 2004-2006 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2004-2007 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
@@ -415,10 +415,7 @@ void audioFileProcessor::playNote( notePlayHandle * _n, bool )
void audioFileProcessor::deleteNotePluginData( notePlayHandle * _n )
{
if( _n->m_pluginData != NULL )
{
m_sampleBuffer.deleteResamplingData( &_n->m_pluginData );
}
m_sampleBuffer.deleteResamplingData( &_n->m_pluginData );
}

View File

@@ -1,7 +1,7 @@
/*
* flp_import.cpp - support for importing FLP-files
*
* Copyright (c) 2006 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2006-2007 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
@@ -739,7 +739,8 @@ bool flpImport::tryImport( trackContainer * _tc )
{
//dump_mem( text, text_len );
const int bpn = 20;
for( Uint32 i = 0; i*bpn < text_len; ++i )
Uint32 imax = ( text_len + bpn - 1 ) / bpn;
for( Uint32 i = 0; i < imax; ++i )
{
int ch = *( text + i*bpn + 6 );
int pos = *( (int *)( text + i*bpn ) );

View File

@@ -45,6 +45,7 @@
* 22 Sep 01, tuorfa@yahoo.com: moved word_dump to here from parse.c
* 22 Sep 01, tuorfa@yahoo.com: added function-level comment blocks
* 29 Mar 05, daved@physiol.usyd.edu.au: changes requested by ZT Smith
* 11 Jan 07, jasp00@users.sourceforge.net: optimized unsafe loop
*--------------------------------------------------------------------*/
#ifdef HAVE_CONFIG_H
@@ -164,10 +165,10 @@ void word_free (Word *w) {
static void
print_indentation (int level)
{
int i;
if (level) {
for (i=0;i<level;i+=2)
/* indent in multiples of 2 */
level = (level >> 1) + (level & 1);
while (level-- > 0)
printf (". ");
} else {
printf ("\n-----------------------------------------------------------------------\n\n");

View File

@@ -1,7 +1,7 @@
/*
* organic.cpp - additive synthesizer for organ-like sounds
*
* Copyright (c) 2006 Andreas Brandmaier <andy/at/brandmaier/dot/de>
* Copyright (c) 2006-2007 Andreas Brandmaier <andy/at/brandmaier/dot/de>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
@@ -402,10 +402,6 @@ void organicInstrument::playNote( notePlayHandle * _n, bool )
void organicInstrument::deleteNotePluginData( notePlayHandle * _n )
{
if( _n->m_pluginData == NULL )
{
return;
}
delete static_cast<oscillator *>( static_cast<oscPtr *>(
_n->m_pluginData )->oscLeft );
delete static_cast<oscillator *>( static_cast<oscPtr *>(

View File

@@ -0,0 +1,37 @@
AUTOMAKE_OPTIONS = foreign 1.4
INCLUDES = -I/usr/include/festival -I/usr/include/speech_tools \
-I$(top_srcdir)/include -I$(top_srcdir)/src/lib -I.
CXXFLAGS += -Wno-non-template-friend
AM_CXXFLAGS := $(AM_CXXFLAGS) $(QT_CXXFLAGS) -DPLUGIN_NAME="singerbot"
%.moc: ./%.h
$(MOC) -o $@ $<
MOC_FILES = ./singerbot.moc
BUILT_SOURCES = $(MOC_FILES) ./embedded_resources.h
EMBEDDED_RESOURCES = $(wildcard *png)
./embedded_resources.h: $(EMBEDDED_RESOURCES)
$(BIN2RES) $(EMBEDDED_RESOURCES) > $@
EXTRA_DIST = $(EMBEDDED_RESOURCES)
CLEANFILES = $(MOC_FILES) ./embedded_resources.h
pkglib_LTLIBRARIES = libsingerbot.la
libsingerbot_la_SOURCES = singerbot.cpp singerbot.h
libsingerbot_la_LDFLAGS = -lFestival -lestools -lestbase -lesd -lncurses
$(libsingerbot_la_SOURCES): ./embedded_resources.h

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

BIN
plugins/singerbot/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

@@ -0,0 +1,446 @@
/*
* singerbot.cpp - a singing bot instrument plugin
*
* Copyright (c) 2007 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
* 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 (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
#ifdef QT4
#include <QtCore/QDir>
#include <QtGui/QLayout>
#include <QtGui/QTextEdit>
#else
#include <qdir.h>
#include <qlayout.h>
#include <qtextedit.h>
#endif
#include "singerbot.h"
#include "buffer_allocator.h"
#include "instrument_track.h"
#include "note_play_handle.h"
#include "pattern.h"
#include "sample_buffer.h"
#include "song_editor.h"
#undef SINGLE_SOURCE_COMPILE
#include "embed.cpp"
#undef HAVE_CONFIG_H
#include <festival.h>
extern "C"
{
plugin::descriptor singerbot_plugin_descriptor =
{
STRINGIFY_PLUGIN_NAME( PLUGIN_NAME ),
"SingerBot",
QT_TRANSLATE_NOOP( "pluginBrowser",
"Singer bot to add some basic vocals" ),
"Javier Serrano Polo <jasp00/at/users.sourceforge.net>",
0x0100,
plugin::Instrument,
new QPixmap( PLUGIN_NAME::getIconPixmap( "logo" ) ),
NULL
} ;
// neccessary for getting instance out of shared lib
plugin * lmms_plugin_main( void * _data )
{
return( new singerBot( static_cast<instrumentTrack *>( _data ) ) );
}
}
singerBot::synThread * singerBot::s_thread = NULL;
singerBot::singerBot( instrumentTrack * _track ) :
instrument( _track, &singerbot_plugin_descriptor )
{
if( !s_thread )
{
s_thread = new synThread();
s_thread->start();
}
setPaletteBackgroundPixmap( PLUGIN_NAME::getIconPixmap( "artwork" ) );
QVBoxLayout * vbox = new QVBoxLayout( this );
vbox->setMargin( 10 );
vbox->setSpacing( 0 );
vbox->addSpacing( 45 );
m_lyrics = new QTextEdit( this );
#ifdef QT4
m_lyrics->setAutoFillBackground( TRUE );
QPalette pal;
pal.setColor( m_lyrics->backgroundRole(), QColor( 64, 64, 64 ) );
m_lyrics->setPalette( pal );
#else
m_lyrics->setTextFormat( PlainText );
m_lyrics->setPaletteBackgroundColor( QColor( 64, 64, 64 ) );
#endif
m_lyrics->setText( "Hello, world!" );
connect( m_lyrics, SIGNAL( textChanged( void ) ),
this, SLOT( lyricsChanged( void ) ) );
vbox->addWidget( m_lyrics );
updateWords();
}
singerBot::~singerBot()
{
}
void singerBot::playNote( notePlayHandle * _n, bool )
{
const Uint32 frames = eng()->getMixer()->framesPerAudioBuffer();
sampleFrame * buf = bufferAllocator::alloc<sampleFrame>( frames );
if( !_n->m_pluginData )
{
createWave( _n );
}
handle_data * hdata = (handle_data *)_n->m_pluginData;
sampleBuffer * sample_buffer = hdata->remaining_frames ?
readWave( hdata ) : new sampleBuffer( NULL, 0, eng() );
if( sample_buffer->play( buf, 0, frames, BASE_FREQ,
FALSE, //loop
&hdata->resampling_data ) )
{
getInstrumentTrack()->processAudioBuffer( buf, frames, _n );
}
sharedObject::unref( sample_buffer );
bufferAllocator::free( buf );
}
void singerBot::deleteNotePluginData( notePlayHandle * _n )
{
handle_data * hdata = (handle_data *)_n->m_pluginData;
if( hdata->resampling_data )
{
sampleBuffer::deleteResamplingData( &hdata->resampling_data );
}
if( hdata->wave )
{
delete hdata->wave;
}
delete hdata;
}
void singerBot::saveSettings( QDomDocument & _doc, QDomElement & _this )
{
QDomElement element = _doc.createElement( "lyrics" );
_this.appendChild( element );
#ifdef QT4
QDomCDATASection ds = _doc.createCDATASection(
m_lyrics->toPlainText() );
#else
QDomCDATASection ds = _doc.createCDATASection( m_lyrics->text() );
#endif
element.appendChild( ds );
}
void singerBot::loadSettings( const QDomElement & _this )
{
#ifdef QT4
m_lyrics->setPlainText(
_this.namedItem( "lyrics" ).toElement().text() );
#else
m_lyrics->setText( _this.namedItem( "lyrics" ).toElement().text() );
#endif
}
QString singerBot::nodeName( void ) const
{
return( singerbot_plugin_descriptor.name );
}
void singerBot::lyricsChanged( void )
{
m_words_dirty = TRUE;
}
void singerBot::updateWords( void )
{
m_words = QStringList::split( ' ',
m_lyrics->text().simplifyWhiteSpace().lower() );
m_words_dirty = FALSE;
}
void singerBot::createWave( notePlayHandle * _n )
{
handle_data * hdata = new handle_data;
_n->m_pluginData = hdata;
hdata->resampling_data = NULL;
hdata->wave = NULL;
hdata->remaining_frames = 0;
if( m_words_dirty )
{
updateWords();
}
if( m_words.empty() )
{
return;
}
hdata->frequency = getInstrumentTrack()->frequency( _n )
/ ( eng()->getMixer()->sampleRate()
/ DEFAULT_SAMPLE_RATE );
hdata->duration = _n->length() > 0 ?
_n->length() * 60.0f * BEATS_PER_TACT
/ 64.0f / eng()->getSongEditor()->getTempo() :
0;
int word_index = _n->patternIndex() % m_words.size();
hdata->text = m_words[word_index].ascii();
s_thread->set_data( hdata );
s_thread->unlock_synth();
s_thread->lock_handle();
if( !hdata->wave )
{
return;
}
hdata->wave->resample( eng()->getMixer()->sampleRate() );
hdata->remaining_frames = hdata->wave->num_samples();
}
sampleBuffer * singerBot::readWave( handle_data * _hdata )
{
f_cnt_t buffer_size = eng()->getMixer()->framesPerAudioBuffer();
f_cnt_t frames = tMin( buffer_size, _hdata->remaining_frames );
f_cnt_t offset = _hdata->wave->num_samples() - _hdata->remaining_frames;
const float fac = 1.0f / OUTPUT_SAMPLE_MULTIPLIER;
sampleFrame * data = new sampleFrame[frames];
for( f_cnt_t frame = 0; frame < frames; ++frame )
{
sample_t wave_sample = _hdata->wave->a( offset + frame ) * fac;
for( ch_cnt_t chnl = 0; chnl < DEFAULT_CHANNELS; ++chnl )
{
data[frame][chnl] = wave_sample;
}
}
sampleBuffer * buffer = new sampleBuffer( data, frames, eng() );
_hdata->remaining_frames -= frames;
delete[] data;
return( buffer );
}
singerBot::synThread::synThread( void ) :
m_handle_semaphore( 1 ),
m_synth_semaphore( 1 )
{
m_handle_semaphore += m_handle_semaphore.total();
m_synth_semaphore += m_synth_semaphore.total();
}
singerBot::synThread::~synThread()
{
m_handle_semaphore -= m_handle_semaphore.total();
m_synth_semaphore -= m_synth_semaphore.total();
}
void singerBot::synThread::run( void )
{
const int load_init_files = 1;
festival_initialize( load_init_files, FESTIVAL_HEAP_SIZE );
festival_eval_command(
"(define get_segment"
" (lambda (utt) (begin"
" (Initialize utt)"
" (Text utt)"
" (Token_POS utt)"
" (Token utt)"
" (POS utt)"
" (Phrasify utt)"
" (Word utt)"
" ))"
")" );
festival_eval_command(
"(Parameter.set 'Int_Method 'DuffInt)" );
festival_eval_command(
"(Parameter.set 'Int_Target_Method Int_Targets_Default)" );
for( ; ; )
{
m_synth_semaphore++;
text_to_wave();
m_handle_semaphore--;
}
}
void singerBot::synThread::text_to_wave( void )
{
char command[80];
sprintf( command,
"(set! duffint_params '((start %f) (end %f)))",
m_data->frequency, m_data->frequency );
festival_eval_command( command );
festival_eval_command(
"(Parameter.set 'Duration_Stretch 1)" );
sprintf( command,
"(set! total_time (parse-number %f))", m_data->duration );
festival_eval_command( command );
festival_eval_command(
"(set! word " + quote_string( m_data->text, "\"", "\\", 1 )
+ ")" );
festival_eval_command(
"(set! my_utt (eval (list 'Utterance 'Text word)))" );
festival_eval_command(
" (get_segment my_utt)" );
festival_eval_command(
"(if (equal? (length (utt.relation.leafs my_utt 'Segment)) 1)"
" (begin (set! my_utt (eval "
"(list 'Utterance 'Text (string-append word \" \" word))))"
" (get_segment my_utt)"
"))" );
festival_eval_command(
" (Pauses my_utt)" );
festival_eval_command(
" (item.delete (utt.relation.first my_utt 'Segment))" );
festival_eval_command(
" (item.delete (utt.relation.last my_utt 'Segment))" );
festival_eval_command(
" (Intonation my_utt)" );
festival_eval_command(
" (PostLex my_utt)" );
festival_eval_command(
" (Duration my_utt)" );
festival_eval_command(
"(if (not (equal? total_time 0)) (begin"
"(set! utt_time"
" (item.feat (utt.relation.last my_utt 'Segment) 'end))"
"(Parameter.set 'Duration_Stretch (/ total_time utt_time))"
"(Duration my_utt)"
"))" );
festival_eval_command(
" (Int_Targets my_utt)" );
if( festival_eval_command(
" (Wave_Synth my_utt)" ) )
{
m_data->wave = get_wave( "my_utt" );
}
else
{
// Unsupported frequency
m_data->wave = NULL;
}
}
EST_Wave * singerBot::synThread::get_wave( const char * _name )
{
LISP lutt = siod_get_lval( _name, NULL );
if( !utterance_p( lutt ) )
{
return( NULL );
}
EST_Relation *r = utterance( lutt )->relation( "Wave" );
//TODO: This check is useless. The error is fatal.
if ( !r || !r->head() )
{
return( NULL );
}
return( new EST_Wave( *wave( r->head()->f( "wave" ) ) ) );
}
#include "singerbot.moc"

View File

@@ -0,0 +1,137 @@
/*
* singerbot.h - declaration of class singerBot, a singing bot instrument plugin
*
* Copyright (c) 2007 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
* 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 (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
#ifndef _SINGERBOT_H
#define _SINGERBOT_H
#ifdef QT4
#include <QtCore/QThread>
#else
#include <qthread.h>
#endif
#include "instrument.h"
class EST_Wave;
class QTextEdit;
class sampleBuffer;
class EST_String;
class singerBot : public instrument
{
Q_OBJECT
public:
singerBot( instrumentTrack * _track );
virtual ~singerBot();
virtual void FASTCALL playNote( notePlayHandle * _n,
bool _try_parallelizing );
virtual void FASTCALL deleteNotePluginData( notePlayHandle * _n );
virtual void FASTCALL saveSettings( QDomDocument & _doc,
QDomElement & _this );
virtual void FASTCALL loadSettings( const QDomElement & _this );
virtual QString nodeName( void ) const;
public slots:
void lyricsChanged( void );
private:
typedef struct
{
void * resampling_data;
EST_Wave * wave;
int remaining_frames;
float frequency;
float duration;
const char * text;
} handle_data;
class synThread : public QThread
{
public:
synThread( void );
virtual ~synThread();
void set_data( handle_data * _hdata )
{
m_data = _hdata;
}
void unlock_synth( void )
{
m_synth_semaphore--;
}
void lock_handle( void )
{
m_handle_semaphore++;
}
protected:
virtual void run( void );
private:
QSemaphore m_handle_semaphore;
QSemaphore m_synth_semaphore;
handle_data * m_data;
void text_to_wave( void );
EST_Wave * get_wave( const char * _name );
} ;
static synThread * s_thread;
QTextEdit * m_lyrics;
QStringList m_words;
bool m_words_dirty;
void createWave( notePlayHandle * _n );
sampleBuffer * readWave( handle_data * _hdata );
void updateWords( void );
} ;
#endif

View File

@@ -1,7 +1,7 @@
/*
* triple_oscillator.cpp - powerful instrument with three oscillators
*
* Copyright (c) 2004-2006 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2004-2007 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
@@ -769,10 +769,6 @@ void tripleOscillator::playNote( notePlayHandle * _n, bool )
void tripleOscillator::deleteNotePluginData( notePlayHandle * _n )
{
if( _n->m_pluginData == NULL )
{
return;
}
delete static_cast<oscillator *>( static_cast<oscPtr *>(
_n->m_pluginData )->oscLeft );
delete static_cast<oscillator *>( static_cast<oscPtr *>(

View File

@@ -1,7 +1,7 @@
/*
* vestige.cpp - instrument-plugin for hosting VST-plugins
*
* Copyright (c) 2005-2006 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2005-2007 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
@@ -354,6 +354,8 @@ void vestigeInstrument::playNote( notePlayHandle * _n, bool )
}
m_plugin->enqueueMidiEvent( midiEvent( NOTE_ON, 0, k,
_n->getVolume() ), _n->framesAhead() );
// notify when the handle stops, call to deleteNotePluginData
_n->m_pluginData = _n;
}
m_pluginMutex.unlock();
}

View File

@@ -4,7 +4,7 @@
* arp_and_chords_tab_widget.cpp - widget for use in arp/chord-tab of
* instrument-track-window
*
* Copyright (c) 2004-2006 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2004-2007 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
@@ -461,7 +461,7 @@ void arpAndChordsTabWidget::processNote( notePlayHandle * _n )
break;
}
// create copy of base-note
note note_copy( NULL, 0, 0,
note note_copy( NULL, _n->length(), 0,
(tones)( sub_note_key %
NOTES_PER_OCTAVE ),
(octaves)( sub_note_key /
@@ -477,6 +477,10 @@ void arpAndChordsTabWidget::processNote( notePlayHandle * _n )
_n->framesAhead(),
_n->frames(), note_copy );
note_play_handle->setBBTrackFrom( _n );
#if SINGERBOT_SUPPORT
note_play_handle->setPatternIndex(
_n->patternIndex() );
#endif
// add sub-note to base-note, now all stuff is
// done by notePlayHandle::play_note()
_n->addSubNote( note_play_handle );
@@ -640,6 +644,9 @@ void arpAndChordsTabWidget::processNote( notePlayHandle * _n )
new_note,
TRUE );
note_play_handle->setBBTrackFrom( _n );
#if SINGERBOT_SUPPORT
note_play_handle->setPatternIndex( _n->patternIndex() );
#endif
// add sub-note to base-note - now all stuff is done by
// notePlayHandle::playNote()

View File

@@ -4,7 +4,7 @@
* note_play_handle.cpp - implementation of class notePlayHandle, part of
* play-engine
*
* Copyright (c) 2004-2006 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2004-2007 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
@@ -59,6 +59,9 @@ notePlayHandle::notePlayHandle( instrumentTrack * _it,
m_arpNote( _arp_note ),
m_muted( FALSE ),
m_bbTrack( NULL )
#if SINGERBOT_SUPPORT
, m_patternIndex( 0 )
#endif
{
// if the instrument is monophonic we do not allow other note-play-
// handles to exist for this track and therefore remove them
@@ -117,7 +120,7 @@ notePlayHandle::~notePlayHandle()
noteOff( 0 );
}
if( m_instrumentTrack != NULL )
if( m_instrumentTrack != NULL && m_pluginData != NULL )
{
m_instrumentTrack->deleteNotePluginData( this );
}
@@ -252,7 +255,10 @@ void notePlayHandle::checkValidity( void )
{
noteOff( 0 );
}
m_instrumentTrack->deleteNotePluginData( this );
if( m_pluginData )
{
m_instrumentTrack->deleteNotePluginData( this );
}
m_instrumentTrack = NULL;
}
// sub-notes might not be registered at mixer (for example arpeggio-

View File

@@ -397,7 +397,7 @@ f_cnt_t sampleBuffer::decodeSampleSDL( const char * _f,
{
AUDIO_S16SYS,
_channels,
_samplerate,
_samplerate
} ;
f_cnt_t frames = 0;

View File

@@ -4,7 +4,7 @@
* instrument_track.cpp - implementation of instrument-track-class
* (window + data-structures)
*
* Copyright (c) 2004-2006 Tobias Doerffel <tobydox/at/users.sourceforge.net>
* Copyright (c) 2004-2007 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
@@ -664,7 +664,9 @@ void instrumentTrack::processInEvent( const midiEvent & _me,
{
m_notesMutex.lock();
m_notes[_me.key()] = nph;
m_notesMutex.unlock();
}
return;
}
break;
}
@@ -777,7 +779,7 @@ QString instrumentTrack::instrumentName( void ) const
void instrumentTrack::deleteNotePluginData( notePlayHandle * _n )
{
if( m_instrument != NULL )
if( m_instrument != NULL && _n->m_pluginData != NULL )
{
m_instrument->deleteNotePluginData( _n );
}
@@ -996,6 +998,9 @@ bool FASTCALL instrumentTrack::play( const midiTime & _start,
noteVector & notes = p->notes();
// ...and set our index to zero
noteVector::iterator it = notes.begin();
#if SINGERBOT_SUPPORT
int note_idx = 0;
#endif
// very effective algorithm for playing notes that are
// posated within the current sample-frame
@@ -1006,6 +1011,12 @@ bool FASTCALL instrumentTrack::play( const midiTime & _start,
// skip notes which are posated before start-tact
while( it != notes.end() && ( *it )->pos() < cur_start )
{
#if SINGERBOT_SUPPORT
if( ( *it )->length() != 0 )
{
++note_idx;
}
#endif
++it;
}
}
@@ -1045,6 +1056,9 @@ bool FASTCALL instrumentTrack::play( const midiTime & _start,
note_frames,
*cur_note );
note_play_handle->setBBTrack( bb_track );
#if SINGERBOT_SUPPORT
note_play_handle->setPatternIndex( note_idx );
#endif
note_play_handle->play( FALSE );
// could we play all within current number of
// frames per audio-buffer?
@@ -1061,6 +1075,9 @@ bool FASTCALL instrumentTrack::play( const midiTime & _start,
delete note_play_handle;
}
played_a_note = TRUE;
#if SINGERBOT_SUPPORT
++note_idx;
#endif
}
++it;
}

View File

@@ -73,7 +73,7 @@
projectNotes::projectNotes( engine * _engine) :
projectNotes::projectNotes( engine * _engine ) :
QMainWindow( _engine->getMainWindow()->workspace()
#ifndef QT4
, 0, Qt::WStyle_Title