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:
@@ -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) \
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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 ) );
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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 *>(
|
||||
|
||||
37
plugins/singerbot/Makefile.am
Normal file
37
plugins/singerbot/Makefile.am
Normal 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
|
||||
BIN
plugins/singerbot/artwork.png
Normal file
BIN
plugins/singerbot/artwork.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 167 KiB |
BIN
plugins/singerbot/logo.png
Normal file
BIN
plugins/singerbot/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.5 KiB |
446
plugins/singerbot/singerbot.cpp
Normal file
446
plugins/singerbot/singerbot.cpp
Normal 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"
|
||||
137
plugins/singerbot/singerbot.h
Normal file
137
plugins/singerbot/singerbot.h
Normal 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
|
||||
@@ -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 *>(
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user