bugfixes, new plugin "Vibed" and more
git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@111 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
48
ChangeLog
48
ChangeLog
@@ -1,5 +1,53 @@
|
||||
2005-03-26 Danny McRae <khjklujn/at/yahoo/dot/com>
|
||||
|
||||
* plugins/vibed/:
|
||||
added "Vibed"-plugin, a powerful combination of PluckedStringSynth and
|
||||
BitInvader that's capable of producing a surprisingly wide range of
|
||||
sounds
|
||||
|
||||
2006-03-26 Tobias Doerffel <tobydox/at/users/dot/sourceforge/dot/net>
|
||||
|
||||
* src/lib/journalling_object.cpp:
|
||||
in journallingObject::saveState(): append new dom-element to parent
|
||||
before calling saveSettings() as some implementations of it depend on
|
||||
knowing something about it's parent (e.g. whether it's the clipboard
|
||||
etc.) - fixes several bugs related to clipboard-usage and drag'n'drop
|
||||
|
||||
2006-03-25 Tobias Doerffel <tobydox/at/users/dot/sourceforge/dot/net>
|
||||
|
||||
* include/instrument_track.h:
|
||||
* src/core/preset_preview_play_handle.cpp:
|
||||
disable journalling for all objects involved in preset-preview
|
||||
|
||||
* src/tracks/instrument_track.cpp:
|
||||
when saving preset, create new node below content-node of project, as
|
||||
the behaviour of saveTrackSpecificSettings() was changed some days
|
||||
before
|
||||
|
||||
* src/lib/mmp.cpp:
|
||||
bugfixes concerning project type-naming
|
||||
|
||||
* src/core/arp_and_chords_tab_widget.cpp:
|
||||
bugfixes concerning loading/saving settings
|
||||
|
||||
2006-03-24 Tobias Doerffel <tobydox/at/users/dot/sourceforge/dot/net>
|
||||
|
||||
* src/core/track.cpp:
|
||||
in trackContentWidget::undoStep(): cast journalling object to
|
||||
track-content-object and close it instead of deleting it - fixes crash
|
||||
after undo of TCO-add
|
||||
|
||||
2006-03-23 Tobias Doerffel <tobydox/at/users/dot/sourceforge/dot/net>
|
||||
|
||||
* plugins/organic/organic.cpp:
|
||||
* plugins/organic/randomise_pressed.png:
|
||||
added pixmap for visual feedback when pressing randomise-button
|
||||
|
||||
* plugins/midi_import/midi_import.cpp:
|
||||
removed attribute FASTCALL from midiImport::tryImport() for not
|
||||
crashing LMMS, as tryImport() is not defined as FASTCALL in
|
||||
importFilter-API
|
||||
|
||||
* src/core/export_project_dialog.cpp:
|
||||
fixed bug causing LMMS to crash when trying to export a project
|
||||
|
||||
|
||||
4
TODO
4
TODO
@@ -1,3 +1,5 @@
|
||||
- when recording MIDI-events, add switch to disable recording of velocity
|
||||
- integrated sample-browser in context-menu of sample-track/-tco
|
||||
- font-size-scaling-coefficient in setup-dialog
|
||||
- make note able of journalling
|
||||
- before calling undoStep/redoStep from journallingObject, save journalling-state-context and disabled journalling, restore afterwards
|
||||
@@ -5,7 +7,6 @@
|
||||
- undo/redo-support in note/track etc.
|
||||
- save tco-settings in trackContentWidget::saveSettings() etc. instead of track::...
|
||||
- restore stacking-order of windows when loading project
|
||||
- fix MIDI-import-filter
|
||||
- bristol-bindings
|
||||
- resample sample-track-tcos when using hq-mode
|
||||
- add support for panes-interface (like blender) (instead of MDI etc.)
|
||||
@@ -25,7 +26,6 @@
|
||||
- level-meters in output-graph and channel-track
|
||||
- do not skip samples because of rounding-errors when resampling in src/lib/sample_buffer.cpp
|
||||
- MIDI-program/MIDI-mapping/process program-/channel-change-events from MIDI-files
|
||||
- add note-len- and note-alignment-selectbox to piano-roll
|
||||
- DSSI-support
|
||||
- somehow avoid hidden plugin-descriptor-widgets plugin-browser if height of window is too small -> add scrollbar
|
||||
- use drawLineF() for drawing notes in pattern::paintEvent() in qt4-version
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ(2.50)
|
||||
AC_INIT(lmms, 0.1.4-cvs20060323, tobydox/at/users/dot/sourceforge/dot/net)
|
||||
AM_INIT_AUTOMAKE(lmms, 0.1.4-cvs20060323)
|
||||
AC_INIT(lmms, 0.1.4-cvs20060326, tobydox/at/users/dot/sourceforge/dot/net)
|
||||
AM_INIT_AUTOMAKE(lmms, 0.1.4-cvs20060326)
|
||||
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
|
||||
@@ -470,6 +470,7 @@ AC_CONFIG_FILES([Makefile
|
||||
plugins/plucked_string_synth/Makefile
|
||||
plugins/triple_oscillator/Makefile
|
||||
plugins/vestige/Makefile
|
||||
plugins/vibed/Makefile
|
||||
lmms.spec])
|
||||
AC_OUTPUT
|
||||
|
||||
|
||||
30
data/presets/TripleOscillator/AnalogTimes2.cs.xml
Normal file
30
data/presets/TripleOscillator/AnalogTimes2.cs.xml
Normal file
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE multimedia-project>
|
||||
<multimediaproject creator="Linux MultiMedia Studio (LMMS)" creatorversion="0.1.4-cvs20060323" type="instrumenttracksettings" version="1.0" >
|
||||
<head/>
|
||||
<instrumenttracksettings>
|
||||
<instrumenttrack width="250" x="12" y="227" surpos="134219776" fxch="0" height="436" baseoct="4" vol="100" name="AnalogTimes 2" basetone="9" tab="1" visible="1" >
|
||||
<tripleoscillator userwavefile1="samples/empty.wav" wavetype1="2" coarse1="0" userwavefile2="samples/empty.wav" wavetype2="0" coarse2="-12" vol0="49" vol1="54" finel0="0" vol2="14" finel1="0" finel2="-14" modalgo1="2" stphdetun0="247" pan0="0" modalgo2="3" stphdetun1="109" pan1="0" stphdetun2="50" pan2="0" phoffset0="0" phoffset1="271" phoffset2="0" finer0="0" finer1="0" finer2="13" userwavefile0="samples/empty.wav" wavetype0="3" coarse0="0" >
|
||||
<journal entries="0" metadata="1" id="391701" curentry="0" />
|
||||
</tripleoscillator>
|
||||
<eldata fres="0.66" ftype="0" fcut="0" fwet="1" >
|
||||
<elvol lfosyncmode="0" lpdel="0" amt="1" rel="0.473" ctlenvamt="0" latt="0" sus="0.433" lspd="0.0917" att="0" pdel="0" lamt="0" dec="0.324" userwavefile="" x100="0" lshp="0" hold="0" >
|
||||
<journal entries="0" metadata="1" id="579409" curentry="0" />
|
||||
</elvol>
|
||||
<elcut lfosyncmode="0" lpdel="0" amt="1" rel="0.43" ctlenvamt="0" latt="0" sus="0.64" lspd="0.767" att="0" pdel="0" lamt="0" dec="0.241" userwavefile="" x100="0" lshp="1" hold="0" >
|
||||
<journal entries="0" metadata="1" id="907107" curentry="0" />
|
||||
</elcut>
|
||||
<elres lfosyncmode="0" lpdel="0" amt="0" rel="0.1" ctlenvamt="0" latt="0" sus="0.499" lspd="0.01" att="0" pdel="0" lamt="-0.01" dec="0.499" userwavefile="" x100="0" lshp="1" hold="0" >
|
||||
<journal entries="0" metadata="1" id="403343" curentry="0" />
|
||||
</elres>
|
||||
<journal entries="0" metadata="1" id="518423" curentry="0" />
|
||||
</eldata>
|
||||
<arpandchords arpmode="0" chordrange="1" arprange="3" arpdisabled="1" chord="0" chorddisabled="0" arpgate="142" arp="0" arpsyncmode="0" arptime="102" arpdir="1" >
|
||||
<journal entries="0" metadata="1" id="485335" curentry="0" />
|
||||
</arpandchords>
|
||||
<midi inputchannel="0" outputchannel="1" receive="1" send="0" inports="24:0 CS46XX:CS46XX" >
|
||||
<journal entries="0" metadata="1" id="192691" curentry="0" />
|
||||
</midi>
|
||||
</instrumenttrack>
|
||||
</instrumenttracksettings>
|
||||
</multimediaproject>
|
||||
@@ -155,6 +155,9 @@ public:
|
||||
virtual void FASTCALL loadTrackSpecificSettings( const QDomElement &
|
||||
_this );
|
||||
|
||||
using track::setJournalling;
|
||||
|
||||
|
||||
// load instrument whose name matches given one
|
||||
instrument * FASTCALL loadInstrument( const QString &
|
||||
_instrument_name );
|
||||
|
||||
@@ -160,7 +160,7 @@ public:
|
||||
int index( void ) const;
|
||||
|
||||
// note-play-handles belonging to given channel
|
||||
static constNotePlayHandleVector nphsOfChannelTrack(
|
||||
static constNotePlayHandleVector nphsOfInstrumentTrack(
|
||||
const instrumentTrack * _ct );
|
||||
|
||||
// return whether given note-play-handle is equal to *this
|
||||
|
||||
@@ -60,7 +60,7 @@ public:
|
||||
virtual bool done( void ) const;
|
||||
|
||||
static void cleanUp( engine * _engine );
|
||||
static constNotePlayHandleVector nphsOfChannelTrack(
|
||||
static constNotePlayHandleVector nphsOfInstrumentTrack(
|
||||
const instrumentTrack * _ct );
|
||||
|
||||
private:
|
||||
|
||||
@@ -90,7 +90,13 @@ public:
|
||||
// journalling information about the ID get's lost
|
||||
void forgetAboutID( const jo_id_t _id );
|
||||
|
||||
void clear( void );
|
||||
void clearJournal( void )
|
||||
{
|
||||
m_journalEntries.clear();
|
||||
m_currentJournalEntry = m_journalEntries.end();
|
||||
}
|
||||
|
||||
void clearInvalidJournallingObjects( void );
|
||||
|
||||
journallingObject * getJournallingObject( const jo_id_t _id )
|
||||
{
|
||||
|
||||
@@ -129,8 +129,8 @@ protected:
|
||||
void setAutoResizeEnabled( bool _e = FALSE );
|
||||
float pixelsPerTact( void );
|
||||
|
||||
virtual void undoStep( journalEntry & _edit_step );
|
||||
virtual void redoStep( journalEntry & _edit_step );
|
||||
virtual void undoStep( journalEntry & _je );
|
||||
virtual void redoStep( journalEntry & _je );
|
||||
|
||||
|
||||
protected slots:
|
||||
@@ -210,8 +210,8 @@ protected:
|
||||
return( "trackcontentwidget" );
|
||||
}
|
||||
|
||||
virtual void undoStep( journalEntry & _edit_step );
|
||||
virtual void redoStep( journalEntry & _edit_step );
|
||||
virtual void undoStep( journalEntry & _je );
|
||||
virtual void redoStep( journalEntry & _je );
|
||||
|
||||
|
||||
private:
|
||||
@@ -277,7 +277,7 @@ private:
|
||||
|
||||
|
||||
// actual widget shown in trackContainer
|
||||
class trackWidget : public QWidget
|
||||
class trackWidget : public QWidget, public journallingObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
@@ -338,6 +338,15 @@ public slots:
|
||||
|
||||
|
||||
protected:
|
||||
virtual void undoStep( journalEntry & _je );
|
||||
virtual void redoStep( journalEntry & _je );
|
||||
|
||||
virtual QString nodeName( void ) const
|
||||
{
|
||||
return( "trackwidget" );
|
||||
}
|
||||
|
||||
|
||||
virtual void dragEnterEvent( QDragEnterEvent * _dee );
|
||||
virtual void dropEvent( QDropEvent * _de );
|
||||
virtual void mousePressEvent( QMouseEvent * _me );
|
||||
|
||||
@@ -129,6 +129,9 @@ public:
|
||||
|
||||
|
||||
protected:
|
||||
virtual void undoStep( journalEntry & _je );
|
||||
virtual void redoStep( journalEntry & _je );
|
||||
|
||||
virtual void dragEnterEvent( QDragEnterEvent * _dee );
|
||||
virtual void dropEvent( QDropEvent * _de );
|
||||
virtual void mousePressEvent( QMouseEvent * _me );
|
||||
@@ -152,6 +155,10 @@ protected slots:
|
||||
|
||||
|
||||
private:
|
||||
enum actions
|
||||
{
|
||||
ADD_TRACK, REMOVE_TRACK
|
||||
} ;
|
||||
|
||||
class scrollArea : public QScrollArea
|
||||
{
|
||||
|
||||
@@ -2,5 +2,5 @@ if VST_SUPPORT
|
||||
VESTIGE_SUBDIR=vestige
|
||||
endif
|
||||
|
||||
SUBDIRS = audio_file_processor bit_invader midi_import organic plucked_string_synth triple_oscillator $(VESTIGE_SUBDIR)
|
||||
SUBDIRS = audio_file_processor bit_invader midi_import organic plucked_string_synth triple_oscillator $(VESTIGE_SUBDIR) vibed
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ midiImport::~midiImport()
|
||||
|
||||
|
||||
|
||||
bool FASTCALL midiImport::tryImport( trackContainer * _tc )
|
||||
bool midiImport::tryImport( trackContainer * _tc )
|
||||
{
|
||||
if( openFile() == FALSE )
|
||||
{
|
||||
|
||||
@@ -184,7 +184,7 @@ organicInstrument::organicInstrument( instrumentTrack * _channel_track ) :
|
||||
m_randBtn = new pixmapButton( this, eng() );
|
||||
m_randBtn->move( 100, 200 );
|
||||
m_randBtn->setActiveGraphic( PLUGIN_NAME::getIconPixmap(
|
||||
"randomise" ) );
|
||||
"randomise_pressed" ) );
|
||||
m_randBtn->setInactiveGraphic( PLUGIN_NAME::getIconPixmap(
|
||||
"randomise" ) );
|
||||
//m_randBtn->setMask( QBitmap( PLUGIN_NAME::getIconPixmap( "btn_mask" ).
|
||||
|
||||
BIN
plugins/organic/randomise_pressed.png
Normal file
BIN
plugins/organic/randomise_pressed.png
Normal file
Binary file not shown.
44
plugins/vibed/Makefile.am
Normal file
44
plugins/vibed/Makefile.am
Normal file
@@ -0,0 +1,44 @@
|
||||
AUTOMAKE_OPTIONS = foreign 1.4
|
||||
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/src/lib -I.
|
||||
|
||||
|
||||
AM_CXXFLAGS := $(AM_CXXFLAGS) $(QT_CXXFLAGS) -DPLUGIN_NAME="vibedstrings"
|
||||
|
||||
|
||||
%.moc: ./%.h
|
||||
$(MOC) -o $@ $<
|
||||
|
||||
|
||||
MOC_FILES = ./vibed.moc ./graph.moc ./impulse_editor.moc ./nine_button_selector.moc
|
||||
|
||||
BUILT_SOURCES = $(MOC_FILES) ./embedded_resources.h
|
||||
EMBEDDED_RESOURCES = $(wildcard *png)
|
||||
|
||||
./embedded_resources.h: $(EMBEDDED_RESOURCES)
|
||||
$(top_builddir)/buildtools/bin2res $(EMBEDDED_RESOURCES) > $@
|
||||
|
||||
EXTRA_DIST = $(EMBEDDED_RESOURCES)
|
||||
|
||||
|
||||
CLEANFILES = $(MOC_FILES) ./embedded_resources.h
|
||||
|
||||
|
||||
|
||||
pkglib_LTLIBRARIES= libvibedstrings.la
|
||||
|
||||
libvibedstrings_la_SOURCES = vibed.cpp \
|
||||
vibed.h \
|
||||
graph.cpp \
|
||||
graph.h \
|
||||
vibrating_string.cpp \
|
||||
vibrating_string.h \
|
||||
string_container.cpp \
|
||||
string_container.h \
|
||||
impulse_editor.cpp \
|
||||
impulse_editor.h \
|
||||
nine_button_selector.cpp \
|
||||
nine_button_selector.h
|
||||
|
||||
$(libvibedstrings_la_SOURCES): ./embedded_resources.h
|
||||
BIN
plugins/vibed/artwork.png
Normal file
BIN
plugins/vibed/artwork.png
Normal file
Binary file not shown.
BIN
plugins/vibed/button_-1_off.png
Normal file
BIN
plugins/vibed/button_-1_off.png
Normal file
Binary file not shown.
BIN
plugins/vibed/button_-1_on.png
Normal file
BIN
plugins/vibed/button_-1_on.png
Normal file
Binary file not shown.
BIN
plugins/vibed/button_-2_off.png
Normal file
BIN
plugins/vibed/button_-2_off.png
Normal file
Binary file not shown.
BIN
plugins/vibed/button_-2_on.png
Normal file
BIN
plugins/vibed/button_-2_on.png
Normal file
Binary file not shown.
BIN
plugins/vibed/button_1_off.png
Normal file
BIN
plugins/vibed/button_1_off.png
Normal file
Binary file not shown.
BIN
plugins/vibed/button_1_on.png
Normal file
BIN
plugins/vibed/button_1_on.png
Normal file
Binary file not shown.
BIN
plugins/vibed/button_2_off.png
Normal file
BIN
plugins/vibed/button_2_off.png
Normal file
Binary file not shown.
BIN
plugins/vibed/button_2_on.png
Normal file
BIN
plugins/vibed/button_2_on.png
Normal file
Binary file not shown.
BIN
plugins/vibed/button_3_off.png
Normal file
BIN
plugins/vibed/button_3_off.png
Normal file
Binary file not shown.
BIN
plugins/vibed/button_3_on.png
Normal file
BIN
plugins/vibed/button_3_on.png
Normal file
Binary file not shown.
BIN
plugins/vibed/button_4_off.png
Normal file
BIN
plugins/vibed/button_4_off.png
Normal file
Binary file not shown.
BIN
plugins/vibed/button_4_on.png
Normal file
BIN
plugins/vibed/button_4_on.png
Normal file
Binary file not shown.
BIN
plugins/vibed/button_5_off.png
Normal file
BIN
plugins/vibed/button_5_off.png
Normal file
Binary file not shown.
BIN
plugins/vibed/button_5_on.png
Normal file
BIN
plugins/vibed/button_5_on.png
Normal file
Binary file not shown.
BIN
plugins/vibed/button_6_off.png
Normal file
BIN
plugins/vibed/button_6_off.png
Normal file
Binary file not shown.
BIN
plugins/vibed/button_6_on.png
Normal file
BIN
plugins/vibed/button_6_on.png
Normal file
Binary file not shown.
BIN
plugins/vibed/button_7_off.png
Normal file
BIN
plugins/vibed/button_7_off.png
Normal file
Binary file not shown.
BIN
plugins/vibed/button_7_on.png
Normal file
BIN
plugins/vibed/button_7_on.png
Normal file
Binary file not shown.
BIN
plugins/vibed/button_8_off.png
Normal file
BIN
plugins/vibed/button_8_off.png
Normal file
Binary file not shown.
BIN
plugins/vibed/button_8_on.png
Normal file
BIN
plugins/vibed/button_8_on.png
Normal file
Binary file not shown.
BIN
plugins/vibed/button_9_off.png
Normal file
BIN
plugins/vibed/button_9_off.png
Normal file
Binary file not shown.
BIN
plugins/vibed/button_9_on.png
Normal file
BIN
plugins/vibed/button_9_on.png
Normal file
Binary file not shown.
BIN
plugins/vibed/button_down.png
Normal file
BIN
plugins/vibed/button_down.png
Normal file
Binary file not shown.
BIN
plugins/vibed/button_f_off.png
Normal file
BIN
plugins/vibed/button_f_off.png
Normal file
Binary file not shown.
BIN
plugins/vibed/button_f_on.png
Normal file
BIN
plugins/vibed/button_f_on.png
Normal file
Binary file not shown.
BIN
plugins/vibed/button_up.png
Normal file
BIN
plugins/vibed/button_up.png
Normal file
Binary file not shown.
265
plugins/vibed/graph.cpp
Normal file
265
plugins/vibed/graph.cpp
Normal file
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* graph.cpp - a QT widget for displaying and manipulating waveforms
|
||||
*
|
||||
* Copyright (c) 2006 Andreas Brandmaier <andy/at/brandmaier/dot/de>
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "qt3support.h"
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <QPaintEvent>
|
||||
#include <QFontMetrics>
|
||||
#include <QPainter>
|
||||
|
||||
#else
|
||||
|
||||
#include <qfontmetrics.h>
|
||||
#include <qpainter.h>
|
||||
#include <qcursor.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "graph.h"
|
||||
#include "string_pair_drag.h"
|
||||
#include "sample_buffer.h"
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
|
||||
graph::graph( QWidget * _parent, engine * _engine ) :
|
||||
QWidget( _parent ),
|
||||
engineObject( _engine )
|
||||
{
|
||||
m_mouseDown = false;
|
||||
|
||||
setFixedSize( 132, 104 );
|
||||
|
||||
setAcceptDrops( TRUE );
|
||||
|
||||
#ifndef QT4
|
||||
setBackgroundMode( NoBackground );
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
graph::~graph()
|
||||
{
|
||||
}
|
||||
|
||||
void graph::setForeground( const QPixmap &_pixmap )
|
||||
{
|
||||
m_foreground = _pixmap;
|
||||
}
|
||||
|
||||
void graph::setSamplePointer( float * _pointer, int _length )
|
||||
{
|
||||
samplePointer = _pointer;
|
||||
sampleLength = _length;
|
||||
update();
|
||||
}
|
||||
|
||||
void graph::loadSampleFromFile( const QString & _filename )
|
||||
{
|
||||
// zero sample_shape
|
||||
for (int i = 0; i < sampleLength; i++)
|
||||
{
|
||||
samplePointer[i] = 0;
|
||||
}
|
||||
|
||||
// load user shape
|
||||
sampleBuffer buffer( eng(), _filename );
|
||||
|
||||
// copy buffer data
|
||||
sampleLength = min( sampleLength, static_cast<int>(buffer.frames()) );
|
||||
for ( int i = 0; i < sampleLength; i++ )
|
||||
{
|
||||
samplePointer[i] = (float)*buffer.data()[i];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void graph::mouseMoveEvent ( QMouseEvent * _me )
|
||||
{
|
||||
// get position
|
||||
int x = _me->x();
|
||||
int y = _me->y();
|
||||
|
||||
|
||||
// avoid mouse leaps
|
||||
int diff = x - m_lastCursorX;
|
||||
|
||||
if( diff >= 1 )
|
||||
{
|
||||
x = m_lastCursorX + 1;
|
||||
}
|
||||
else if( diff <= 1 )
|
||||
{
|
||||
x = m_lastCursorX - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = m_lastCursorX;
|
||||
}
|
||||
|
||||
changeSampleAt( x, y );
|
||||
|
||||
// update mouse
|
||||
m_lastCursorX = x;
|
||||
|
||||
}
|
||||
|
||||
void graph::mousePressEvent( QMouseEvent * _me )
|
||||
{
|
||||
if( _me->button() == Qt::LeftButton )
|
||||
{
|
||||
// toggle mouse state
|
||||
m_mouseDown = true;
|
||||
|
||||
// get position
|
||||
int x = _me->x();
|
||||
int y = _me->y();
|
||||
|
||||
changeSampleAt( x,y );
|
||||
|
||||
// toggle mouse state
|
||||
m_mouseDown = true;
|
||||
#ifndef QT3
|
||||
setCursor( Qt::BlankCursor );
|
||||
#else
|
||||
setCursor( QCursor::BlankCursor );
|
||||
#endif
|
||||
m_lastCursorX = x;
|
||||
}
|
||||
}
|
||||
|
||||
void graph::changeSampleAt(int _x, int _y)
|
||||
{
|
||||
// consider border of background image
|
||||
_x -= 2;
|
||||
_y -= 2;
|
||||
|
||||
// boundary check
|
||||
if (_x < 0) { return; }
|
||||
if (_x > sampleLength) { return; }
|
||||
if (_y < 0) { return; }
|
||||
if (_y >= 100) { return; }
|
||||
_y = 100 - _y;
|
||||
|
||||
// change sample shape
|
||||
samplePointer[_x] = (_y-50.0)/50.0;
|
||||
emit sampleChanged();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void graph::mouseReleaseEvent( QMouseEvent * _me )
|
||||
{
|
||||
if( _me->button() == Qt::LeftButton )
|
||||
{
|
||||
// toggle mouse state
|
||||
m_mouseDown = false;
|
||||
#ifndef QT3
|
||||
setCursor( Qt::ArrowCursor );
|
||||
#else
|
||||
setCursor( QCursor::ArrowCursor );
|
||||
#endif
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void graph::paintEvent( QPaintEvent * )
|
||||
{
|
||||
|
||||
#ifdef QT4
|
||||
QPainter p( this );
|
||||
#else
|
||||
QPixmap draw_pm( rect().size() );
|
||||
draw_pm.fill( this, rect().topLeft() );
|
||||
|
||||
QPainter p( &draw_pm, this );
|
||||
#endif
|
||||
|
||||
p.setPen( QColor( 0xFF, 0xAA, 0x00 ) );
|
||||
|
||||
p.drawLine( 1+sampleLength, 2, 1+sampleLength, 102);
|
||||
|
||||
float xscale = 128.0 / sampleLength;
|
||||
|
||||
for (int i=0; i < sampleLength-1; i++)
|
||||
{
|
||||
p.drawLine(2+static_cast<int>(i*xscale),
|
||||
2+static_cast<int>(-samplePointer[i]*50) + 50,
|
||||
2+static_cast<int>((i+1)*xscale),
|
||||
2+static_cast<int>(-samplePointer[i+1]*50 + 50)
|
||||
);
|
||||
}
|
||||
|
||||
// draw Pointer
|
||||
if (m_mouseDown) {
|
||||
QPoint cursor = mapFromGlobal( QCursor::pos() );
|
||||
p.setPen( QColor( 0xAA, 0xFF, 0x00 ) );
|
||||
p.drawLine( 2, cursor.y(), 130, cursor.y() );
|
||||
p.drawLine( cursor.x(), 2, cursor.x(), 102 );
|
||||
}
|
||||
p.drawPixmap( 0, 0, m_foreground );
|
||||
|
||||
#ifndef QT4
|
||||
// and blit all the drawn stuff on the screen...
|
||||
bitBlt( this, rect().topLeft(), &draw_pm );
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
void graph::dropEvent( QDropEvent * _de )
|
||||
{
|
||||
QString type = stringPairDrag::decodeKey( _de );
|
||||
QString value = stringPairDrag::decodeValue( _de );
|
||||
|
||||
if( type == "samplefile" )
|
||||
{
|
||||
loadSampleFromFile( value );
|
||||
_de->accept();
|
||||
}
|
||||
}
|
||||
|
||||
void graph::dragEnterEvent( QDragEnterEvent * _dee )
|
||||
{
|
||||
if( stringPairDrag::processDragEnterEvent( _dee,
|
||||
QString( "samplefile" ) ) == FALSE )
|
||||
{
|
||||
_dee->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#include "graph.moc"
|
||||
87
plugins/vibed/graph.h
Normal file
87
plugins/vibed/graph.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* graph.h - a QT widget for displaying and manipulating waveforms
|
||||
*
|
||||
* Copyright (c) 2006 Andreas Brandmaier <andy/at/brandmaier/dot/de>
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _GRAPH_H
|
||||
#define _GRAPH_H
|
||||
|
||||
#include "qt3support.h"
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <QWidget>
|
||||
#include <QPixmap>
|
||||
#include <QCursor>
|
||||
|
||||
#else
|
||||
|
||||
#include <qwidget.h>
|
||||
#include <qpixmap.h>
|
||||
#include <qcursor.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "engine.h"
|
||||
|
||||
|
||||
class graph : public QWidget, public engineObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
graph( QWidget * _parent, engine * _engine );
|
||||
virtual ~graph();
|
||||
|
||||
void setSamplePointer( float * pointer, int length );
|
||||
void setForeground( const QPixmap & _pixmap );
|
||||
void loadSampleFromFile( const QString & _filename );
|
||||
|
||||
signals:
|
||||
void sampleSizeChanged( float f );
|
||||
void sampleChanged( void );
|
||||
|
||||
protected:
|
||||
virtual void paintEvent( QPaintEvent * _pe );
|
||||
virtual void dropEvent( QDropEvent * _de );
|
||||
virtual void dragEnterEvent( QDragEnterEvent * _dee );
|
||||
virtual void mousePressEvent( QMouseEvent * _me );
|
||||
virtual void mouseMoveEvent( QMouseEvent * _me );
|
||||
virtual void mouseReleaseEvent( QMouseEvent * _me );
|
||||
|
||||
private:
|
||||
|
||||
void changeSampleAt(int _x, int _y);
|
||||
|
||||
QPixmap m_foreground;
|
||||
|
||||
|
||||
float *samplePointer;
|
||||
int sampleLength;
|
||||
|
||||
bool m_mouseDown;
|
||||
int m_lastCursorX;
|
||||
|
||||
} ;
|
||||
|
||||
#endif
|
||||
492
plugins/vibed/impulse_editor.cpp
Normal file
492
plugins/vibed/impulse_editor.cpp
Normal file
@@ -0,0 +1,492 @@
|
||||
/*
|
||||
* impulse_editor.cpp - graphic waveform editor
|
||||
*
|
||||
* Copyright (c) 2006 Danny McRae <khjklujn/at/yahoo/com>
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qt3support.h"
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <QPoint>
|
||||
#include <Qt/QtXml>
|
||||
#include <QMap>
|
||||
#include <QLabel>
|
||||
#include <QMenu>
|
||||
|
||||
#else
|
||||
|
||||
#include <qpoint.h>
|
||||
#include <qdom.h>
|
||||
#include <qmap.h>
|
||||
#include <qwhatsthis.h>
|
||||
#include <qlabel.h>
|
||||
#include <qpopupmenu.h>
|
||||
#include <qcursor.h>
|
||||
|
||||
#endif
|
||||
|
||||
#include "impulse_editor.h"
|
||||
#include "vibed.h"
|
||||
#include "tooltip.h"
|
||||
#include "oscillator.h"
|
||||
#include "song_editor.h"
|
||||
|
||||
|
||||
impulseEditor::impulseEditor( QWidget * _parent, int _x, int _y,
|
||||
engine * _engine, Uint32 _len ) :
|
||||
QWidget( _parent, "impulseEditor" ),
|
||||
engineObject( _engine ),
|
||||
m_sampleLength( _len ),
|
||||
m_normalizeFactor( 1.0f ),
|
||||
m_forward( TRUE )
|
||||
{
|
||||
setFixedSize( 153, 124 );
|
||||
m_base = QPixmap::grabWidget( _parent, _x, _y );
|
||||
setPaletteBackgroundPixmap( m_base );
|
||||
|
||||
m_graph = new graph( this, eng() );
|
||||
m_graph->setForeground( PLUGIN_NAME::getIconPixmap( "wavegraph4" ) );
|
||||
m_graph->move( 0, 0 );
|
||||
m_graph->setCursor( QCursor( Qt::CrossCursor ) );
|
||||
toolTip::add( m_graph, tr ( "Draw your own waveform here "
|
||||
"by dragging your mouse onto this graph" ) );
|
||||
|
||||
connect( m_graph, SIGNAL ( sampleChanged( void ) ),
|
||||
this, SLOT ( sampleChanged( void ) ) );
|
||||
|
||||
m_sinWaveBtn = new pixmapButton( this, eng() );
|
||||
m_sinWaveBtn->move( 136, 3 );
|
||||
m_sinWaveBtn->setActiveGraphic( embed::getIconPixmap(
|
||||
"sin_wave_active" ) );
|
||||
m_sinWaveBtn->setInactiveGraphic( embed::getIconPixmap(
|
||||
"sin_wave_inactive" ) );
|
||||
m_sinWaveBtn->setChecked( TRUE );
|
||||
toolTip::add( m_sinWaveBtn,
|
||||
tr( "Click here if you want a sine-wave for "
|
||||
"current oscillator." ) );
|
||||
connect( m_sinWaveBtn, SIGNAL (clicked ( void ) ),
|
||||
this, SLOT ( sinWaveClicked( void ) ) );
|
||||
|
||||
|
||||
m_triangleWaveBtn = new pixmapButton( this, eng() );
|
||||
m_triangleWaveBtn->move( 136, 20 );
|
||||
m_triangleWaveBtn->setActiveGraphic(
|
||||
embed::getIconPixmap( "triangle_wave_active" ) );
|
||||
m_triangleWaveBtn->setInactiveGraphic(
|
||||
embed::getIconPixmap( "triangle_wave_inactive" ) );
|
||||
toolTip::add( m_triangleWaveBtn,
|
||||
tr( "Click here if you want a triangle-wave "
|
||||
"for current oscillator." ) );
|
||||
connect( m_triangleWaveBtn, SIGNAL ( clicked ( void ) ),
|
||||
this, SLOT ( triangleWaveClicked( void ) ) );
|
||||
|
||||
|
||||
m_sawWaveBtn = new pixmapButton( this, eng() );
|
||||
m_sawWaveBtn->move( 136, 37 );
|
||||
m_sawWaveBtn->setActiveGraphic( embed::getIconPixmap(
|
||||
"saw_wave_active" ) );
|
||||
m_sawWaveBtn->setInactiveGraphic( embed::getIconPixmap(
|
||||
"saw_wave_inactive" ) );
|
||||
toolTip::add( m_sawWaveBtn,
|
||||
tr( "Click here if you want a saw-wave for "
|
||||
"current oscillator." ) );
|
||||
connect( m_sawWaveBtn, SIGNAL (clicked ( void ) ),
|
||||
this, SLOT ( sawWaveClicked( void ) ) );
|
||||
|
||||
|
||||
m_sqrWaveBtn = new pixmapButton( this, eng() );
|
||||
m_sqrWaveBtn->move( 136, 54 );
|
||||
m_sqrWaveBtn->setActiveGraphic( embed::getIconPixmap(
|
||||
"square_wave_active" ) );
|
||||
m_sqrWaveBtn->setInactiveGraphic( embed::getIconPixmap(
|
||||
"square_wave_inactive" ) );
|
||||
toolTip::add( m_sqrWaveBtn,
|
||||
tr( "Click here if you want a square-wave for "
|
||||
"current oscillator." ) );
|
||||
connect( m_sqrWaveBtn, SIGNAL ( clicked ( void ) ),
|
||||
this, SLOT ( sqrWaveClicked( void ) ) );
|
||||
|
||||
|
||||
m_whiteNoiseWaveBtn = new pixmapButton( this, eng() );
|
||||
m_whiteNoiseWaveBtn->move( 136, 71 );
|
||||
m_whiteNoiseWaveBtn->setActiveGraphic(
|
||||
embed::getIconPixmap( "white_noise_wave_active" ) );
|
||||
m_whiteNoiseWaveBtn->setInactiveGraphic(
|
||||
embed::getIconPixmap( "white_noise_wave_inactive" ) );
|
||||
toolTip::add( m_whiteNoiseWaveBtn,
|
||||
tr( "Click here if you want a white-noise for "
|
||||
"current oscillator." ) );
|
||||
connect( m_whiteNoiseWaveBtn, SIGNAL ( clicked ( void ) ),
|
||||
this, SLOT ( noiseWaveClicked( void ) ) );
|
||||
|
||||
|
||||
m_usrWaveBtn = new pixmapButton( this, eng() );
|
||||
m_usrWaveBtn->move( 136, 88 );
|
||||
m_usrWaveBtn->setActiveGraphic( embed::getIconPixmap(
|
||||
"usr_wave_active" ) );
|
||||
m_usrWaveBtn->setInactiveGraphic( embed::getIconPixmap(
|
||||
"usr_wave_inactive" ) );
|
||||
toolTip::add( m_usrWaveBtn,
|
||||
tr( "Click here if you want a user-defined "
|
||||
"wave-shape for current oscillator." ) );
|
||||
connect( m_usrWaveBtn, SIGNAL ( clicked ( void ) ),
|
||||
this, SLOT ( usrWaveClicked( void ) ) );
|
||||
|
||||
|
||||
m_smoothBtn = new pixmapButton( this, eng() );
|
||||
m_smoothBtn->move( 3, 108 );
|
||||
m_smoothBtn->setActiveGraphic( PLUGIN_NAME::getIconPixmap(
|
||||
"smooth_active" ) );
|
||||
m_smoothBtn->setInactiveGraphic( PLUGIN_NAME::getIconPixmap(
|
||||
"smooth_inactive" ) );
|
||||
m_smoothBtn->setChecked( FALSE );
|
||||
toolTip::add( m_smoothBtn,
|
||||
tr( "Click here to smooth waveform." ) );
|
||||
connect( m_smoothBtn, SIGNAL ( clicked ( void ) ),
|
||||
this, SLOT ( smoothClicked( void ) ) );
|
||||
|
||||
|
||||
m_normalizeBtn = new pixmapButton( this, eng() );
|
||||
m_normalizeBtn->move( 20, 108 );
|
||||
m_normalizeBtn->setActiveGraphic( PLUGIN_NAME::getIconPixmap(
|
||||
"normalize_active" ) );
|
||||
m_normalizeBtn->setInactiveGraphic( PLUGIN_NAME::getIconPixmap(
|
||||
"normalize_inactive" ) );
|
||||
m_normalizeBtn->setChecked( FALSE );
|
||||
toolTip::add( m_normalizeBtn,
|
||||
tr( "Click here to normalize waveform." ) );
|
||||
|
||||
connect( m_normalizeBtn, SIGNAL ( clicked ( void ) ),
|
||||
this, SLOT ( normalizeClicked( void ) ) );
|
||||
|
||||
m_state = new ledCheckBox( "", this, eng() );
|
||||
m_state->move( 136, 109 );
|
||||
m_state->setChecked( TRUE );
|
||||
toolTip::add( m_state,
|
||||
tr( "Click here to enable/disable waveform." ) );
|
||||
|
||||
m_sampleShape = new float[m_sampleLength];
|
||||
m_graph->setSamplePointer( m_sampleShape, m_sampleLength );
|
||||
|
||||
m_lastBtn = m_sinWaveBtn;
|
||||
emit( sinWaveClicked() );
|
||||
|
||||
move( _x, _y );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
impulseEditor::~impulseEditor()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void impulseEditor::sinWaveClicked( void )
|
||||
{
|
||||
m_lastBtn->setChecked( FALSE);
|
||||
m_lastBtn = m_sinWaveBtn;
|
||||
m_lastBtn->setChecked( TRUE );
|
||||
// generate a Sinus wave using static oscillator-method
|
||||
for( Uint32 i = 0; i < m_sampleLength; i++ )
|
||||
{
|
||||
m_sampleShape[i] = oscillator::sinSample( i /
|
||||
static_cast<float>( m_sampleLength ) );
|
||||
}
|
||||
|
||||
sampleChanged();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void impulseEditor::triangleWaveClicked( void )
|
||||
{
|
||||
m_lastBtn->setChecked( FALSE);
|
||||
m_lastBtn = m_triangleWaveBtn;
|
||||
m_lastBtn->setChecked( TRUE );
|
||||
// generate a Triangle wave using static oscillator-method
|
||||
for( Uint32 i = 0; i < m_sampleLength; i++ )
|
||||
{
|
||||
m_sampleShape[i] = oscillator::triangleSample( i /
|
||||
static_cast<float>( m_sampleLength ) );
|
||||
}
|
||||
|
||||
sampleChanged();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void impulseEditor::sawWaveClicked( void )
|
||||
{
|
||||
m_lastBtn->setChecked( FALSE);
|
||||
m_lastBtn = m_sawWaveBtn;
|
||||
m_lastBtn->setChecked( TRUE );
|
||||
// generate a Saw wave using static oscillator-method
|
||||
for( Uint32 i = 0; i < m_sampleLength; i++ )
|
||||
{
|
||||
m_sampleShape[i] = oscillator::sawSample( i /
|
||||
static_cast<float>( m_sampleLength ) );
|
||||
}
|
||||
|
||||
sampleChanged();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void impulseEditor::sqrWaveClicked( void )
|
||||
{
|
||||
m_lastBtn->setChecked( FALSE);
|
||||
m_lastBtn = m_sqrWaveBtn;
|
||||
m_lastBtn->setChecked( TRUE );
|
||||
// generate a Sqr wave using static oscillator-method
|
||||
for( Uint32 i = 0; i < m_sampleLength; i++ )
|
||||
{
|
||||
m_sampleShape[i] = oscillator::squareSample( i /
|
||||
static_cast<float>( m_sampleLength ) );
|
||||
}
|
||||
|
||||
sampleChanged();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void impulseEditor::noiseWaveClicked( void )
|
||||
{
|
||||
m_lastBtn->setChecked( FALSE);
|
||||
m_lastBtn = m_whiteNoiseWaveBtn;
|
||||
m_lastBtn->setChecked( TRUE );
|
||||
// generate a Noise wave using static oscillator-method
|
||||
for( Uint32 i = 0; i < m_sampleLength; i++ )
|
||||
{
|
||||
m_sampleShape[i] = oscillator::noiseSample( i /
|
||||
static_cast<float>( m_sampleLength ) );
|
||||
}
|
||||
|
||||
sampleChanged();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void impulseEditor::usrWaveClicked( void )
|
||||
{
|
||||
m_lastBtn->setChecked( FALSE);
|
||||
m_lastBtn = m_usrWaveBtn;
|
||||
m_lastBtn->setChecked( TRUE );
|
||||
// zero sample_shape
|
||||
for( Uint32 i = 0; i < m_sampleLength; i++ )
|
||||
{
|
||||
m_sampleShape[i] = 0;
|
||||
}
|
||||
|
||||
// load user shape
|
||||
sampleBuffer buffer( eng() );
|
||||
QString af = buffer.openAudioFile();
|
||||
if( af != "" )
|
||||
{
|
||||
buffer.setAudioFile( af );
|
||||
|
||||
// copy buffer data
|
||||
if( m_sampleLength < static_cast<Uint32>( buffer.frames() ) )
|
||||
{
|
||||
m_sampleLength = m_sampleLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sampleLength = static_cast<int>( buffer.frames() );
|
||||
}
|
||||
for( Uint32 i = 0; i < m_sampleLength; i++ )
|
||||
{
|
||||
m_sampleShape[i] = static_cast<float>(
|
||||
buffer.data()[0][i] );
|
||||
}
|
||||
}
|
||||
|
||||
sampleChanged();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void impulseEditor::smoothClicked( void )
|
||||
{
|
||||
m_smoothBtn->setChecked( TRUE );
|
||||
m_smoothBtn->update();
|
||||
|
||||
float* temp = new float[m_sampleLength];
|
||||
memcpy( temp, m_sampleShape, sizeof( float ) * m_sampleLength );
|
||||
|
||||
// Smoothing
|
||||
m_sampleShape[0] = temp[0] / 2.0f;
|
||||
for( Uint32 i = 1; i < m_sampleLength - 1; i++ )
|
||||
{
|
||||
m_sampleShape[i] = ( temp[i - 1] +
|
||||
temp[i] +
|
||||
temp[i + 1] ) / 3.0f;
|
||||
}
|
||||
m_sampleShape[m_sampleLength - 1] = temp[m_sampleLength - 1] / 2.0f;
|
||||
m_forward = FALSE;
|
||||
|
||||
// Clean up
|
||||
delete[] temp;
|
||||
|
||||
// paint
|
||||
update();
|
||||
m_graph->update();
|
||||
|
||||
eng()->getSongEditor()->setModified();
|
||||
|
||||
m_smoothBtn->setChecked( FALSE );
|
||||
m_smoothBtn->update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void impulseEditor::normalizeClicked( void )
|
||||
{
|
||||
m_normalizeBtn->setChecked( TRUE );
|
||||
m_normalizeBtn->update();
|
||||
|
||||
float max = 0.0001f;
|
||||
for( Uint32 i = 0; i < m_sampleLength; i++ )
|
||||
{
|
||||
if( fabsf(m_sampleShape[i]) > max && m_sampleShape[i] != 0.0f )
|
||||
{
|
||||
max = fabs( m_sampleShape[i] );
|
||||
}
|
||||
}
|
||||
m_normalizeFactor = max;
|
||||
|
||||
for( Uint32 i = 0; i < m_sampleLength; i++ )
|
||||
{
|
||||
m_sampleShape[i] /= m_normalizeFactor;
|
||||
}
|
||||
|
||||
update();
|
||||
m_graph->update();
|
||||
|
||||
eng()->getSongEditor()->setModified();
|
||||
|
||||
m_normalizeBtn->setChecked( FALSE );
|
||||
m_normalizeBtn->update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void impulseEditor::sampleChanged()
|
||||
{
|
||||
// analyze
|
||||
float max = 0.0001f;
|
||||
for( Uint32 i = 0; i < m_sampleLength; i++ )
|
||||
{
|
||||
if( fabsf(m_sampleShape[i]) > max && m_sampleShape[i] != 0.0f )
|
||||
{
|
||||
max = fabs( m_sampleShape[i] );
|
||||
}
|
||||
}
|
||||
m_normalizeFactor = max;
|
||||
|
||||
// update
|
||||
if( m_graph != NULL )
|
||||
{
|
||||
m_graph->update();
|
||||
}
|
||||
|
||||
eng()->getSongEditor()->setModified();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void impulseEditor::setOn( bool _on )
|
||||
{
|
||||
if( _on )
|
||||
{
|
||||
m_state->setChecked( TRUE );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_state->setChecked( FALSE );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void impulseEditor::contextMenuEvent( QContextMenuEvent * )
|
||||
{
|
||||
QMenu contextMenu( this );
|
||||
#ifdef QT4
|
||||
contextMenu.setTitle( accessibleName() );
|
||||
#else
|
||||
QLabel * caption = new QLabel( "<font color=white><b>" +
|
||||
QString( "Impulse Editor" ) + "</b></font>", this );
|
||||
caption->setPaletteBackgroundColor( QColor( 0, 0, 192 ) );
|
||||
caption->setAlignment( Qt::AlignCenter );
|
||||
contextMenu.addAction( caption );
|
||||
#endif
|
||||
contextMenu.addAction( embed::getIconPixmap( "help" ), tr( "&Help" ),
|
||||
this, SLOT( displayHelp() ) );
|
||||
contextMenu.exec( QCursor::pos() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void impulseEditor::displayHelp( void )
|
||||
{
|
||||
#ifdef QT4
|
||||
QWhatsThis::showText( mapToGlobal( rect().bottomRight() ),
|
||||
whatsThis() );
|
||||
#else
|
||||
QWhatsThis::display( QWhatsThis::textFor( this ), mapToGlobal(
|
||||
rect().bottomRight() ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FASTCALL impulseEditor::setValues( float * _shape )
|
||||
{
|
||||
for( Uint32 i = 0; i < m_sampleLength; i++ )
|
||||
{
|
||||
m_sampleShape[i] = _shape[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#include "impulse_editor.moc"
|
||||
|
||||
99
plugins/vibed/impulse_editor.h
Normal file
99
plugins/vibed/impulse_editor.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* impulse_editor.cpp - graphic waveform editor
|
||||
*
|
||||
* Copyright (c) 2006 Danny McRae <khjklujn/at/yahoo/com>
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
#ifndef _IMPULSE_EDITOR_H
|
||||
#define _IMPULSE_EDITOR_H
|
||||
|
||||
#include "qt3support.h"
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <QWidget>
|
||||
#include <QPixmap>
|
||||
#include <QCursor>
|
||||
|
||||
#else
|
||||
|
||||
#include <qwidget.h>
|
||||
#include <qpixmap.h>
|
||||
#include <qcursor.h>
|
||||
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
#include "types.h"
|
||||
#include "graph.h"
|
||||
#include "pixmap_button.h"
|
||||
#include "engine.h"
|
||||
#include "led_checkbox.h"
|
||||
|
||||
class impulseEditor: public QWidget, public engineObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
impulseEditor( QWidget *parent, int _x, int _y,
|
||||
engine * _engine, Uint32 _len = 128 );
|
||||
~impulseEditor();
|
||||
|
||||
inline float * getValues() { return( m_sampleShape ); };
|
||||
inline bool isOn() { return( m_state->isChecked() ); };
|
||||
void FASTCALL setValues( float * _shape );
|
||||
|
||||
public slots:
|
||||
void sinWaveClicked( void );
|
||||
void triangleWaveClicked( void );
|
||||
void sawWaveClicked( void );
|
||||
void sqrWaveClicked( void );
|
||||
void noiseWaveClicked( void );
|
||||
void usrWaveClicked( void );
|
||||
void smoothClicked( void );
|
||||
void normalizeClicked( void );
|
||||
void sampleChanged();
|
||||
void setOn( bool _on );
|
||||
void contextMenuEvent( QContextMenuEvent * );
|
||||
void displayHelp( void );
|
||||
|
||||
private:
|
||||
|
||||
graph * m_graph;
|
||||
pixmapButton * m_sinWaveBtn;
|
||||
pixmapButton * m_triangleWaveBtn;
|
||||
pixmapButton * m_sqrWaveBtn;
|
||||
pixmapButton * m_sawWaveBtn;
|
||||
pixmapButton * m_whiteNoiseWaveBtn;
|
||||
pixmapButton * m_usrWaveBtn;
|
||||
pixmapButton * m_smoothBtn;
|
||||
pixmapButton * m_normalizeBtn;
|
||||
pixmapButton * m_lastBtn;
|
||||
ledCheckBox * m_state;
|
||||
|
||||
float * m_sampleShape;
|
||||
|
||||
Uint32 m_sampleLength;
|
||||
float m_normalizeFactor;
|
||||
bool m_forward;
|
||||
|
||||
QPixmap m_base;
|
||||
};
|
||||
|
||||
#endif
|
||||
BIN
plugins/vibed/logo.png
Normal file
BIN
plugins/vibed/logo.png
Normal file
Binary file not shown.
318
plugins/vibed/nine_button_selector.cpp
Normal file
318
plugins/vibed/nine_button_selector.cpp
Normal file
@@ -0,0 +1,318 @@
|
||||
/*
|
||||
* nine_button_selector.cpp
|
||||
*
|
||||
* Copyright (c) 2006 Danny McRae <khjklujn/at/yahoo/com>
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <QLabel>
|
||||
#include <QMenu>
|
||||
|
||||
#else
|
||||
|
||||
#include <qwhatsthis.h>
|
||||
#include <qlabel.h>
|
||||
#include <qpopupmenu.h>
|
||||
#include <qcursor.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "nine_button_selector.h"
|
||||
#include "embed.h"
|
||||
|
||||
nineButtonSelector::nineButtonSelector( QPixmap _button0_on,
|
||||
QPixmap _button0_off,
|
||||
QPixmap _button1_on,
|
||||
QPixmap _button1_off,
|
||||
QPixmap _button2_on,
|
||||
QPixmap _button2_off,
|
||||
QPixmap _button3_on,
|
||||
QPixmap _button3_off,
|
||||
QPixmap _button4_on,
|
||||
QPixmap _button4_off,
|
||||
QPixmap _button5_on,
|
||||
QPixmap _button5_off,
|
||||
QPixmap _button6_on,
|
||||
QPixmap _button6_off,
|
||||
QPixmap _button7_on,
|
||||
QPixmap _button7_off,
|
||||
QPixmap _button8_on,
|
||||
QPixmap _button8_off,
|
||||
Uint8 _default,
|
||||
Uint32 _x, Uint32 _y,
|
||||
QWidget * _parent,
|
||||
engine * _engine ):
|
||||
QWidget( _parent, "nineButtonSelector" ),
|
||||
engineObject( _engine ),
|
||||
m_selected( _default )
|
||||
{
|
||||
setFixedSize( 50, 50 );
|
||||
m_base = QPixmap::grabWidget( _parent, _x, _y );
|
||||
move( _x, _y );
|
||||
setPaletteBackgroundPixmap( m_base );
|
||||
|
||||
m_button = new pixmapButton( this, eng() );
|
||||
m_button->move( 1, 1 );
|
||||
m_button->setActiveGraphic( _button0_on );
|
||||
m_button->setInactiveGraphic( _button0_off );
|
||||
m_button->setChecked( FALSE );
|
||||
connect( m_button, SIGNAL ( clicked ( void ) ),
|
||||
this, SLOT ( button0Clicked( void ) ) );
|
||||
m_buttons.append( m_button );
|
||||
|
||||
m_button = new pixmapButton( this, eng() );
|
||||
m_button->move( 18, 1 );
|
||||
m_button->setActiveGraphic( _button1_on );
|
||||
m_button->setInactiveGraphic( _button1_off );
|
||||
m_button->setChecked( FALSE );
|
||||
connect( m_button, SIGNAL ( clicked ( void ) ),
|
||||
this, SLOT ( button1Clicked( void ) ) );
|
||||
m_buttons.append( m_button );
|
||||
|
||||
m_button = new pixmapButton( this, eng() );
|
||||
m_button->move( 35, 1 );
|
||||
m_button->setActiveGraphic( _button2_on );
|
||||
m_button->setInactiveGraphic( _button2_off );
|
||||
m_button->setChecked( FALSE );
|
||||
connect( m_button, SIGNAL ( clicked ( void ) ),
|
||||
this, SLOT ( button2Clicked( void ) ) );
|
||||
m_buttons.append( m_button );
|
||||
|
||||
m_button = new pixmapButton( this, eng() );
|
||||
m_button->move( 1, 18 );
|
||||
m_button->setActiveGraphic( _button3_on );
|
||||
m_button->setInactiveGraphic( _button3_off );
|
||||
m_button->setChecked( FALSE );
|
||||
connect( m_button, SIGNAL ( clicked ( void ) ),
|
||||
this, SLOT ( button3Clicked( void ) ) );
|
||||
m_buttons.append( m_button );
|
||||
|
||||
m_button = new pixmapButton( this, eng() );
|
||||
m_button->move( 18, 18 );
|
||||
m_button->setActiveGraphic( _button4_on );
|
||||
m_button->setInactiveGraphic( _button4_off );
|
||||
m_button->setChecked( FALSE );
|
||||
connect( m_button, SIGNAL ( clicked ( void ) ),
|
||||
this, SLOT ( button4Clicked( void ) ) );
|
||||
m_buttons.append( m_button );
|
||||
|
||||
m_button = new pixmapButton( this, eng() );
|
||||
m_button->move( 35, 18 );
|
||||
m_button->setActiveGraphic( _button5_on );
|
||||
m_button->setInactiveGraphic( _button5_off );
|
||||
m_button->setChecked( FALSE );
|
||||
connect( m_button, SIGNAL ( clicked ( void ) ),
|
||||
this, SLOT ( button5Clicked( void ) ) );
|
||||
m_buttons.append( m_button );
|
||||
|
||||
m_button = new pixmapButton( this, eng() );
|
||||
m_button->move( 1, 35 );
|
||||
m_button->setActiveGraphic( _button6_on );
|
||||
m_button->setInactiveGraphic( _button6_off );
|
||||
m_button->setChecked( FALSE );
|
||||
connect( m_button, SIGNAL ( clicked ( void ) ),
|
||||
this, SLOT ( button6Clicked( void ) ) );
|
||||
m_buttons.append( m_button );
|
||||
|
||||
m_button = new pixmapButton( this, eng() );
|
||||
m_button->move( 18, 35 );
|
||||
m_button->setActiveGraphic( _button7_on );
|
||||
m_button->setInactiveGraphic( _button7_off );
|
||||
m_button->setChecked( FALSE );
|
||||
connect( m_button, SIGNAL ( clicked ( void ) ),
|
||||
this, SLOT ( button7Clicked( void ) ) );
|
||||
m_buttons.append( m_button );
|
||||
|
||||
m_button = new pixmapButton( this, eng() );
|
||||
m_button->move( 35, 35 );
|
||||
m_button->setActiveGraphic( _button8_on );
|
||||
m_button->setInactiveGraphic( _button8_off );
|
||||
m_button->setChecked( FALSE );
|
||||
connect( m_button, SIGNAL ( clicked ( void ) ),
|
||||
this, SLOT ( button8Clicked( void ) ) );
|
||||
m_buttons.append( m_button );
|
||||
|
||||
m_lastBtn = m_buttons.at( _default );
|
||||
m_lastBtn->setChecked( TRUE );
|
||||
}
|
||||
|
||||
|
||||
nineButtonSelector::~ nineButtonSelector()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void nineButtonSelector::button0Clicked( void )
|
||||
{
|
||||
m_lastBtn->setChecked( FALSE);
|
||||
m_lastBtn = m_buttons.at( 0 );
|
||||
m_lastBtn->setChecked( TRUE );
|
||||
|
||||
m_selected = 0;
|
||||
emit nineButtonSelection( m_selected );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void nineButtonSelector::button1Clicked( void )
|
||||
{
|
||||
m_lastBtn->setChecked( FALSE);
|
||||
m_lastBtn = m_buttons.at( 1 );
|
||||
m_lastBtn->setChecked( TRUE );
|
||||
|
||||
m_selected = 1;
|
||||
emit nineButtonSelection( m_selected );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void nineButtonSelector::button2Clicked( void )
|
||||
{
|
||||
m_lastBtn->setChecked( FALSE);
|
||||
m_lastBtn = m_buttons.at( 2 );
|
||||
m_lastBtn->setChecked( TRUE );
|
||||
|
||||
m_selected = 2;
|
||||
emit nineButtonSelection( m_selected );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void nineButtonSelector::button3Clicked( void )
|
||||
{
|
||||
m_lastBtn->setChecked( FALSE);
|
||||
m_lastBtn = m_buttons.at( 3 );
|
||||
m_lastBtn->setChecked( TRUE );
|
||||
|
||||
m_selected = 3;
|
||||
emit nineButtonSelection( m_selected );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void nineButtonSelector::button4Clicked( void )
|
||||
{
|
||||
m_lastBtn->setChecked( FALSE);
|
||||
m_lastBtn = m_buttons.at( 4 );
|
||||
m_lastBtn->setChecked( TRUE );
|
||||
|
||||
m_selected = 4;
|
||||
emit nineButtonSelection( m_selected );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void nineButtonSelector::button5Clicked( void )
|
||||
{
|
||||
m_lastBtn->setChecked( FALSE);
|
||||
m_lastBtn = m_buttons.at( 5 );
|
||||
m_lastBtn->setChecked( TRUE );
|
||||
|
||||
m_selected = 5;
|
||||
emit nineButtonSelection( m_selected );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void nineButtonSelector::button6Clicked( void )
|
||||
{
|
||||
m_lastBtn->setChecked( FALSE);
|
||||
m_lastBtn = m_buttons.at( 6 );
|
||||
m_lastBtn->setChecked( TRUE );
|
||||
|
||||
m_selected = 6;
|
||||
emit nineButtonSelection( m_selected );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void nineButtonSelector::button7Clicked( void )
|
||||
{
|
||||
m_lastBtn->setChecked( FALSE);
|
||||
m_lastBtn = m_buttons.at( 7 );
|
||||
m_lastBtn->setChecked( TRUE );
|
||||
|
||||
m_selected = 7;
|
||||
emit nineButtonSelection( m_selected );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void nineButtonSelector::button8Clicked( void )
|
||||
{
|
||||
m_lastBtn->setChecked( FALSE);
|
||||
m_lastBtn = m_buttons.at( 8 );
|
||||
m_lastBtn->setChecked( TRUE );
|
||||
|
||||
m_selected = 8;
|
||||
emit nineButtonSelection( m_selected );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void nineButtonSelector::contextMenuEvent( QContextMenuEvent * )
|
||||
{
|
||||
QMenu contextMenu( this );
|
||||
#ifdef QT4
|
||||
contextMenu.setTitle( accessibleName() );
|
||||
#else
|
||||
QLabel * caption = new QLabel( "<font color=white><b>" +
|
||||
QString( "Selector" ) + "</b></font>", this );
|
||||
caption->setPaletteBackgroundColor( QColor( 0, 0, 192 ) );
|
||||
caption->setAlignment( Qt::AlignCenter );
|
||||
contextMenu.addAction( caption );
|
||||
#endif
|
||||
contextMenu.addAction( embed::getIconPixmap( "help" ), tr( "&Help" ),
|
||||
this, SLOT( displayHelp() ) );
|
||||
contextMenu.exec( QCursor::pos() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void nineButtonSelector::displayHelp( void )
|
||||
{
|
||||
#ifdef QT4
|
||||
QWhatsThis::showText( mapToGlobal( rect().bottomRight() ),
|
||||
whatsThis() );
|
||||
#else
|
||||
QWhatsThis::display( QWhatsThis::textFor( this ), mapToGlobal(
|
||||
rect().bottomRight() ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#include "nine_button_selector.moc"
|
||||
89
plugins/vibed/nine_button_selector.h
Normal file
89
plugins/vibed/nine_button_selector.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* nine_button_selector.h
|
||||
*
|
||||
* Copyright (c) 2006 Danny McRae <khjklujn/at/yahoo/com>
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
#ifndef _NINE_BUTTON_SELECTOR_H
|
||||
#define _NINE_BUTTON_SELECTOR_H
|
||||
|
||||
#include <qptrlist.h>
|
||||
|
||||
#include "qt3support.h"
|
||||
#include "config.h"
|
||||
#include "types.h"
|
||||
#include "pixmap_button.h"
|
||||
|
||||
class nineButtonSelector: public QWidget, public engineObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
nineButtonSelector( QPixmap _button1_on,
|
||||
QPixmap _button1_off,
|
||||
QPixmap _button2_on,
|
||||
QPixmap _button2_off,
|
||||
QPixmap _button3_on,
|
||||
QPixmap _button3_off,
|
||||
QPixmap _button4_on,
|
||||
QPixmap _button4_off,
|
||||
QPixmap _button5_on,
|
||||
QPixmap _button5_off,
|
||||
QPixmap _button6_on,
|
||||
QPixmap _button6_off,
|
||||
QPixmap _button7_on,
|
||||
QPixmap _button7_off,
|
||||
QPixmap _button8_on,
|
||||
QPixmap _button8_off,
|
||||
QPixmap _button9_on,
|
||||
QPixmap _button9_off,
|
||||
Uint8 _default,
|
||||
Uint32 _x, Uint32 _y,
|
||||
QWidget * _parent,
|
||||
engine * _engine );
|
||||
~nineButtonSelector();
|
||||
|
||||
inline Uint8 getSelected() { return( m_selected ); };
|
||||
|
||||
public slots:
|
||||
void button0Clicked( void );
|
||||
void button1Clicked( void );
|
||||
void button2Clicked( void );
|
||||
void button3Clicked( void );
|
||||
void button4Clicked( void );
|
||||
void button5Clicked( void );
|
||||
void button6Clicked( void );
|
||||
void button7Clicked( void );
|
||||
void button8Clicked( void );
|
||||
void contextMenuEvent( QContextMenuEvent * );
|
||||
void displayHelp( void );
|
||||
|
||||
signals:
|
||||
void nineButtonSelection( Uint8 );
|
||||
|
||||
private:
|
||||
QPtrList<pixmapButton> m_buttons;
|
||||
pixmapButton * m_button;
|
||||
pixmapButton * m_lastBtn;
|
||||
QPixmap m_base;
|
||||
|
||||
Uint8 m_selected;
|
||||
};
|
||||
#endif
|
||||
BIN
plugins/vibed/normalize_active.png
Normal file
BIN
plugins/vibed/normalize_active.png
Normal file
Binary file not shown.
BIN
plugins/vibed/normalize_inactive.png
Normal file
BIN
plugins/vibed/normalize_inactive.png
Normal file
Binary file not shown.
BIN
plugins/vibed/smooth_active.png
Normal file
BIN
plugins/vibed/smooth_active.png
Normal file
Binary file not shown.
BIN
plugins/vibed/smooth_inactive.png
Normal file
BIN
plugins/vibed/smooth_inactive.png
Normal file
Binary file not shown.
95
plugins/vibed/string_container.cpp
Normal file
95
plugins/vibed/string_container.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* string_container.cpp - contains a collection of strings
|
||||
*
|
||||
* Copyright (c) 2006 Danny McRae <khjklujn/at/yahoo/com>
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "string_container.h"
|
||||
|
||||
|
||||
stringContainer::stringContainer( const float _pitch,
|
||||
const sample_rate_t _sample_rate,
|
||||
const Uint32 _buffer_length ) :
|
||||
m_pitch( _pitch ),
|
||||
m_sampleRate( _sample_rate ),
|
||||
m_bufferLength( _buffer_length )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void stringContainer::addString(Uint8 _harm,
|
||||
const float _pick,
|
||||
const float _pickup,
|
||||
float * _impluse,
|
||||
const float _randomize,
|
||||
const float _string_loss,
|
||||
const float _detune,
|
||||
const Uint8 _oversample,
|
||||
const bool _state )
|
||||
{
|
||||
float harm;
|
||||
switch( _harm )
|
||||
{
|
||||
case 0:
|
||||
harm = 0.25f;
|
||||
break;
|
||||
case 1:
|
||||
harm = 0.5f;
|
||||
break;
|
||||
case 2:
|
||||
harm = 1.0f;
|
||||
break;
|
||||
case 3:
|
||||
harm = 2.0f;
|
||||
break;
|
||||
case 4:
|
||||
harm = 3.0f;
|
||||
break;
|
||||
case 5:
|
||||
harm = 4.0f;
|
||||
break;
|
||||
case 6:
|
||||
harm = 5.0f;
|
||||
break;
|
||||
case 7:
|
||||
harm = 6.0f;
|
||||
break;
|
||||
case 8:
|
||||
harm = 7.0f;
|
||||
break;
|
||||
default:
|
||||
harm = 1.0f;
|
||||
}
|
||||
|
||||
m_strings.append( new vibratingString( m_pitch * harm,
|
||||
_pick,
|
||||
_pickup,
|
||||
_impluse,
|
||||
m_bufferLength,
|
||||
m_sampleRate,
|
||||
_oversample,
|
||||
_randomize,
|
||||
_string_loss,
|
||||
_detune,
|
||||
_state ) );
|
||||
}
|
||||
83
plugins/vibed/string_container.h
Normal file
83
plugins/vibed/string_container.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/* string_container.h - contains a collection of strings
|
||||
*
|
||||
* Copyright (c) 2006 Danny McRae <khjklujn/at/yahoo/com>
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
#ifndef _TWO_STRINGS_H
|
||||
#define _TWO_STRINGS_H
|
||||
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <Qt3Support>
|
||||
|
||||
#else
|
||||
|
||||
#include "qptrlist.h"
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "config.h"
|
||||
#include "types.h"
|
||||
#include "vibrating_string.h"
|
||||
|
||||
|
||||
|
||||
class stringContainer
|
||||
{
|
||||
public:
|
||||
stringContainer( const float _pitch,
|
||||
const sample_rate_t _sample_rate,
|
||||
const Uint32 _buffer_length );
|
||||
|
||||
void addString( Uint8 _harm,
|
||||
const float _pick,
|
||||
const float _pickup,
|
||||
float * _impluse,
|
||||
const float _randomize,
|
||||
const float _string_loss,
|
||||
const float _detune,
|
||||
const Uint8 _oversample,
|
||||
const bool _state );
|
||||
|
||||
inline ~stringContainer()
|
||||
{
|
||||
m_strings.setAutoDelete( TRUE );
|
||||
Uint32 strings = m_strings.count();
|
||||
for( Uint32 i = 0; i < strings; i++ )
|
||||
{
|
||||
m_strings.removeFirst();
|
||||
}
|
||||
}
|
||||
|
||||
inline float getStringSample( Uint8 _string )
|
||||
{
|
||||
return( m_strings.at( _string )->nextSample() );
|
||||
}
|
||||
|
||||
private:
|
||||
QPtrList<vibratingString> m_strings;
|
||||
const float m_pitch;
|
||||
const sample_rate_t m_sampleRate;
|
||||
const Uint32 m_bufferLength;
|
||||
} ;
|
||||
|
||||
#endif
|
||||
747
plugins/vibed/vibed.cpp
Normal file
747
plugins/vibed/vibed.cpp
Normal file
@@ -0,0 +1,747 @@
|
||||
/*
|
||||
* vibed.cpp - combination of PluckedStringSynth and BitInvader
|
||||
*
|
||||
* Copyright (c) 2006 Danny McRae <khjklujn/at/yahoo/com>
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qt3support.h"
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
#include <Qt/QtXml>
|
||||
#include <QMap>
|
||||
#include <QLabel>
|
||||
#include <QMenu>
|
||||
|
||||
#else
|
||||
|
||||
#include <qdom.h>
|
||||
#include <qmap.h>
|
||||
#include <qwhatsthis.h>
|
||||
#include <qlabel.h>
|
||||
#include <qpopupmenu.h>
|
||||
#include <qcursor.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "vibed.h"
|
||||
#include "note_play_handle.h"
|
||||
#include "instrument_track.h"
|
||||
#include "templates.h"
|
||||
#include "buffer_allocator.h"
|
||||
#include "knob.h"
|
||||
#include "tooltip.h"
|
||||
#include "oscillator.h"
|
||||
#include "song_editor.h"
|
||||
#include "string_container.h"
|
||||
#include "base64.h"
|
||||
|
||||
#undef SINGLE_SOURCE_COMPILE
|
||||
#include "embed.cpp"
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
plugin::descriptor vibedstrings_plugin_descriptor =
|
||||
{
|
||||
STRINGIFY_PLUGIN_NAME( PLUGIN_NAME ),
|
||||
"Vibed",
|
||||
QT_TRANSLATE_NOOP( "pluginBrowser",
|
||||
"Vibrating string modeler" ),
|
||||
"Danny McRae <khjklujn/at/yahoo/com>",
|
||||
0x0100,
|
||||
plugin::INSTRUMENT,
|
||||
new QPixmap( PLUGIN_NAME::getIconPixmap( "logo" ) )
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
vibed::vibed( instrumentTrack * _channel_track ) :
|
||||
instrument( _channel_track, &vibedstrings_plugin_descriptor ),
|
||||
m_sampleLength( 128 )
|
||||
{
|
||||
#ifdef QT4
|
||||
QPalette pal;
|
||||
pal.setBrush( backgroundRole(), PLUGIN_NAME::getIconPixmap(
|
||||
"artwork" ) );
|
||||
setPalette( pal );
|
||||
#else
|
||||
setErasePixmap( PLUGIN_NAME::getIconPixmap( "artwork" ) );
|
||||
#endif
|
||||
|
||||
for( Uint8 harm = 0; harm < 9; harm++ )
|
||||
{
|
||||
m_editor = new impulseEditor( this, 76, 21, eng() );
|
||||
m_editor->setOn( FALSE );
|
||||
m_editor->hide();
|
||||
m_editors.append( m_editor );
|
||||
#ifdef QT4
|
||||
m_editor->setWhatsThis(
|
||||
#else
|
||||
QWhatsThis::add( m_editor,
|
||||
#endif
|
||||
tr(
|
||||
"The waveform editor provides control over the initial state or impulse "
|
||||
"that is used to start the string vibrating. The buttons to the right of "
|
||||
"the graph will initialize the waveform to the selected type. The '?' "
|
||||
"button will load a waveform from a file--only the first 128 samples "
|
||||
"will be loaded.\n\n"
|
||||
|
||||
"The waveform can also be drawn in the graph.\n\n"
|
||||
|
||||
"The 'S' button will smooth the waveform.\n\n"
|
||||
|
||||
"The 'N' button will normalize the waveform.") );
|
||||
|
||||
m_volumeKnob = new knob( knobBright_26, this,
|
||||
tr( "Volume" ),
|
||||
eng() );
|
||||
m_volumeKnob->setRange( 0.0f, 2.0f, 0.01f );
|
||||
m_volumeKnob->setInitValue( 1.0f );
|
||||
m_volumeKnob->move( 103, 142 );
|
||||
m_volumeKnob->setHintText( tr( "Volume:" ) + " ", "" );
|
||||
m_volumeKnob->hide();
|
||||
m_volumeKnobs.append( m_volumeKnob );
|
||||
#ifdef QT4
|
||||
m_volumeKnob->setWhatsThis(
|
||||
#else
|
||||
QWhatsThis::add( m_volumeKnob,
|
||||
#endif
|
||||
tr(
|
||||
"The 'V' knob sets the volume of the selected string." ) );
|
||||
|
||||
m_stiffnessKnob = new knob( knobBright_26, this,
|
||||
tr( "String stiffness" ),
|
||||
eng() );
|
||||
m_stiffnessKnob->setRange( 0.0f, 0.05f, 0.001f );
|
||||
m_stiffnessKnob->setInitValue( 0.0f );
|
||||
m_stiffnessKnob->move( 129, 142 );
|
||||
m_stiffnessKnob->setHintText( tr( "String stiffness:" ) +
|
||||
" ", "" );
|
||||
m_stiffnessKnob->hide();
|
||||
m_stiffnessKnobs.append( m_stiffnessKnob );
|
||||
#ifdef QT4
|
||||
m_stiffnessKnob->setWhatsThis(
|
||||
#else
|
||||
QWhatsThis::add( m_stiffnessKnob,
|
||||
#endif
|
||||
tr(
|
||||
"The 'S' knob sets the stiffness of the selected string. The stiffness "
|
||||
"of the string affects how long the string will ring out. The lower "
|
||||
"the setting, the longer the string will ring." ) );
|
||||
|
||||
|
||||
m_pickKnob = new knob( knobBright_26, this,
|
||||
tr( "Pick position" ),
|
||||
eng() );
|
||||
m_pickKnob->setRange( 0.0f, 0.5f, 0.005f );
|
||||
m_pickKnob->setInitValue( 0.0f );
|
||||
m_pickKnob->move( 153, 142 );
|
||||
m_pickKnob->setHintText( tr( "Pick position:" ) + " ", "" );
|
||||
m_pickKnob->hide();
|
||||
m_pickKnobs.append( m_pickKnob );
|
||||
#ifdef QT4
|
||||
m_pickKnob->setWhatsThis(
|
||||
#else
|
||||
QWhatsThis::add( m_pickKnob,
|
||||
#endif
|
||||
tr(
|
||||
"The 'P' knob sets the position where the selected string will be 'picked'. "
|
||||
"The lower the setting the closer the pick is to the bridge." ) );
|
||||
|
||||
m_pickupKnob = new knob( knobBright_26, this,
|
||||
tr( "Pickup position" ),
|
||||
eng() );
|
||||
m_pickupKnob->setRange( 0.0f, 0.5f, 0.005f );
|
||||
m_pickupKnob->setInitValue( 0.05f );
|
||||
m_pickupKnob->move( 177, 142 );
|
||||
m_pickupKnob->setHintText( tr( "Pickup position:" ) +
|
||||
" ", "" );
|
||||
m_pickupKnob->hide();
|
||||
m_pickupKnobs.append( m_pickupKnob );
|
||||
#ifdef QT4
|
||||
m_pickupKnob->setWhatsThis(
|
||||
#else
|
||||
QWhatsThis::add( m_pickupKnob,
|
||||
#endif
|
||||
tr(
|
||||
"The 'PU' knob sets the position where the vibrations will be monitored "
|
||||
"for the selected string. The lower the setting, the closer the "
|
||||
"pickup is to the bridge." ) );
|
||||
|
||||
m_panKnob = new knob( knobBright_26, this,
|
||||
tr( "Pan" ),
|
||||
eng() );
|
||||
m_panKnob->setRange( -1.0f, 1.0f, 0.01f );
|
||||
m_panKnob->setInitValue( 0.0f );
|
||||
m_panKnob->move( 105, 187 );
|
||||
m_panKnob->setHintText( tr( "Pan:" ) + " ", "" );
|
||||
m_panKnob->hide();
|
||||
m_panKnobs.append( m_panKnob );
|
||||
#ifdef QT4
|
||||
m_panKnob->setWhatsThis(
|
||||
#else
|
||||
QWhatsThis::add( m_panKnob,
|
||||
#endif
|
||||
tr(
|
||||
"The Pan knob determines the location of the selected string in the stereo "
|
||||
"field." ) );
|
||||
|
||||
m_detuneKnob = new knob( knobBright_26, this,
|
||||
tr( "Detune" ),
|
||||
eng() );
|
||||
m_detuneKnob->setRange( -0.1f, 0.1f, 0.001f );
|
||||
m_detuneKnob->setInitValue( 0.0f );
|
||||
m_detuneKnob->move( 150, 187 );
|
||||
m_detuneKnob->setHintText( tr( "Detune:" ) + " ", "" );
|
||||
m_detuneKnob->hide();
|
||||
m_detuneKnobs.append( m_detuneKnob );
|
||||
#ifdef QT4
|
||||
m_detuneKnob->setWhatsThis(
|
||||
#else
|
||||
QWhatsThis::add( m_detuneKnob,
|
||||
#endif
|
||||
tr(
|
||||
"The Detune knob modifies the pitch of the selected string. Settings less "
|
||||
"than zero will cause the string to sound flat. Settings greater than zero "
|
||||
"will cause the string to sound sharp." ) );
|
||||
|
||||
m_randomKnob = new knob( knobBright_26, this,
|
||||
tr( "Fuzziness" ),
|
||||
eng() );
|
||||
m_randomKnob->setRange( 0.0f, 0.75f, 0.01f );
|
||||
m_randomKnob->setInitValue( 0.0f );
|
||||
m_randomKnob->move( 194, 187 );
|
||||
m_randomKnob->setHintText( tr( "Fuzziness:" ) +
|
||||
" ", "" );
|
||||
m_randomKnob->hide();
|
||||
m_randomKnobs.append( m_randomKnob );
|
||||
#ifdef QT4
|
||||
m_randomKnob->setWhatsThis(
|
||||
#else
|
||||
QWhatsThis::add( m_randomKnob,
|
||||
#endif
|
||||
tr(
|
||||
"The Slap knob adds a bit of fuzz to the selected string which is most "
|
||||
"apparent during the attack, though it can also be used to make the string "
|
||||
"sound more 'metallic'.") );
|
||||
|
||||
m_lengthKnob = new knob( knobBright_26, this,
|
||||
tr( "Length" ),
|
||||
eng() );
|
||||
m_lengthKnob->setRange( 1, 16, 1 );
|
||||
m_lengthKnob->setInitValue( 1 );
|
||||
m_lengthKnob->move( 23, 193 );
|
||||
m_lengthKnob->setHintText( tr( "Length:" ) +
|
||||
" ", "" );
|
||||
m_lengthKnob->hide();
|
||||
m_lengthKnobs.append( m_lengthKnob );
|
||||
#ifdef QT4
|
||||
m_lengthKnob->setWhatsThis(
|
||||
#else
|
||||
QWhatsThis::add( m_lengthKnob,
|
||||
#endif
|
||||
tr(
|
||||
"The Length knob sets the length of the selected string. Longer strings "
|
||||
"will both ring longer and sound brighter, however, they will also eat up "
|
||||
"more CPU cycles." ) );
|
||||
|
||||
m_impulse = new ledCheckBox( "", this, eng() );
|
||||
m_impulse->move( 23, 94 );
|
||||
m_impulse->setChecked( FALSE );
|
||||
toolTip::add( m_impulse,
|
||||
tr( "Impulse or initial state" ) );
|
||||
m_impulse->hide();
|
||||
m_impulses.append( m_impulse );
|
||||
#ifdef QT4
|
||||
m_impulse->setWhatsThis(
|
||||
#else
|
||||
QWhatsThis::add( m_impulse,
|
||||
#endif
|
||||
tr(
|
||||
"The 'Imp' selector determines whether the waveform in the graph is to be "
|
||||
"treated as an impulse imparted to the string by the pick or the initial "
|
||||
"state of the string." ) );
|
||||
|
||||
m_harmonic = new nineButtonSelector(
|
||||
PLUGIN_NAME::getIconPixmap( "button_-2_on" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_-2_off" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_-1_on" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_-1_off" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_f_on" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_f_off" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_2_on" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_2_off" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_3_on" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_3_off" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_4_on" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_4_off" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_5_on" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_5_off" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_6_on" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_6_off" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_7_on" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_7_off" ),
|
||||
2,
|
||||
21, 127,
|
||||
this,
|
||||
eng() );
|
||||
m_harmonic->hide();
|
||||
m_harmonics.append( m_harmonic );
|
||||
#ifdef QT4
|
||||
m_harmonic->setWhatsThis(
|
||||
#else
|
||||
QWhatsThis::add( m_harmonic,
|
||||
#endif
|
||||
tr(
|
||||
"The Octave selector is used to choose which harmonic of the note the "
|
||||
"string will ring at. For example, '-2' means the string will ring two "
|
||||
"octaves below the fundamental, 'F' means the string will ring at the "
|
||||
"fundamental, and '6' means the string will ring six octaves above the "
|
||||
"fundamental." ) );
|
||||
}
|
||||
|
||||
m_stringSelector = new nineButtonSelector(
|
||||
PLUGIN_NAME::getIconPixmap( "button_1_on" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_1_off" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_2_on" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_2_off" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_3_on" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_3_off" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_4_on" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_4_off" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_5_on" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_5_off" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_6_on" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_6_off" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_7_on" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_7_off" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_8_on" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_8_off" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_9_on" ),
|
||||
PLUGIN_NAME::getIconPixmap( "button_9_off" ),
|
||||
0,
|
||||
21, 39,
|
||||
this,
|
||||
eng() );
|
||||
connect( m_stringSelector, SIGNAL( nineButtonSelection( Uint8 ) ),
|
||||
this, SLOT( showString( Uint8 ) ) );
|
||||
#ifdef QT4
|
||||
m_stringSelector->setWhatsThis(
|
||||
#else
|
||||
QWhatsThis::add( m_stringSelector,
|
||||
#endif
|
||||
tr(
|
||||
"The String selector is used to choose which string the controls are "
|
||||
"editting. A Vibed instrument can contain up to nine independently "
|
||||
"vibrating strings. The LED in the lower right corner of the "
|
||||
"waveform editor indicates whether the selected string is active." ) );
|
||||
|
||||
m_pickKnob = m_pickKnobs.at( 0 );
|
||||
m_pickupKnob = m_pickupKnobs.at( 0 );
|
||||
m_stiffnessKnob = m_stiffnessKnobs.at( 0 );
|
||||
m_volumeKnob = m_volumeKnobs.at( 0 );
|
||||
m_panKnob = m_panKnobs.at( 0 );
|
||||
m_detuneKnob = m_detuneKnobs.at( 0 );
|
||||
m_randomKnob = m_randomKnobs.at( 0 );
|
||||
m_lengthKnob = m_lengthKnobs.at( 0 );
|
||||
m_editor = m_editors.at( 0 );
|
||||
m_impulse = m_impulses.at( 0 );
|
||||
m_harmonic = m_harmonics.at( 0 );
|
||||
|
||||
m_editor->setOn( TRUE );
|
||||
showString( 0 );
|
||||
|
||||
#ifdef QT4
|
||||
this->setWhatsThis(
|
||||
#else
|
||||
QWhatsThis::add( this,
|
||||
#endif
|
||||
tr(
|
||||
"Vibed models up to nine independently vibrating strings. The 'String' "
|
||||
"selector allows you to choose which string is being edited. The 'Imp' " "selector chooses whether the graph represents an impulse or the initial "
|
||||
"state of the string. The 'Octave' selector chooses which harmonic the "
|
||||
"string should vibrate at.\n\n"
|
||||
|
||||
"The graph allows you to control the initial state or impulse used to set the "
|
||||
"string in motion.\n\n"
|
||||
|
||||
"The 'V' knob controls the volume. The 'S' knob controls the string's "
|
||||
"stiffness. The 'P' knob controls the pick position. The 'PU' knob "
|
||||
"controls the pickup position.\n\n"
|
||||
|
||||
"'Pan' and 'Detune' hopefully don't need explanation. The 'Slap' knob "
|
||||
"adds a bit of fuzz to the sound of the string.\n\n"
|
||||
|
||||
"The 'Length' knob controls the length of the string.\n\n"
|
||||
|
||||
"The LED in the lower right corner of the waveform editor determines "
|
||||
"whether the string is active in the current instrument." ) );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
vibed::~vibed()
|
||||
{
|
||||
delete m_sampleBuffer;
|
||||
m_pickKnobs.setAutoDelete( TRUE );
|
||||
m_pickupKnobs.setAutoDelete( TRUE );
|
||||
m_stiffnessKnobs.setAutoDelete( TRUE );
|
||||
m_volumeKnobs.setAutoDelete( TRUE );
|
||||
m_panKnobs.setAutoDelete( TRUE );
|
||||
m_detuneKnobs.setAutoDelete( TRUE );
|
||||
m_randomKnobs.setAutoDelete( TRUE );
|
||||
m_lengthKnobs.setAutoDelete( TRUE );
|
||||
m_editors.setAutoDelete( TRUE );
|
||||
m_impulses.setAutoDelete( TRUE );
|
||||
for( Uint8 harm = 0; harm < 9; harm++ )
|
||||
{
|
||||
m_pickKnobs.removeFirst();
|
||||
m_pickupKnobs.removeFirst();
|
||||
m_stiffnessKnobs.removeFirst();
|
||||
m_volumeKnobs.removeFirst();
|
||||
m_panKnobs.removeFirst();
|
||||
m_detuneKnobs.removeFirst();
|
||||
m_randomKnobs.removeFirst();
|
||||
m_lengthKnobs.removeFirst();
|
||||
m_editors.removeFirst();
|
||||
m_impulses.removeFirst();
|
||||
m_harmonics.removeFirst();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void vibed::saveSettings( QDomDocument & _doc,
|
||||
QDomElement & _this )
|
||||
{
|
||||
QString name;
|
||||
|
||||
// Save plugin version
|
||||
_this.setAttribute( "version", "0.1" );
|
||||
|
||||
for( Uint8 i = 0; i < 9; i++ )
|
||||
{
|
||||
name = "active" + QString::number( i );
|
||||
_this.setAttribute( name, QString::number(
|
||||
m_editors.at( i )->isOn() ) );
|
||||
if( m_editors.at( i )->isOn() )
|
||||
{
|
||||
name = "volume" + QString::number( i );
|
||||
_this.setAttribute( name, QString::number(
|
||||
m_volumeKnobs.at( i )->value() ) );
|
||||
|
||||
name = "stiffness" + QString::number( i );
|
||||
_this.setAttribute( name, QString::number(
|
||||
m_stiffnessKnobs.at( i )->value() ) );
|
||||
|
||||
name = "pick" + QString::number( i );
|
||||
_this.setAttribute( name, QString::number(
|
||||
m_pickKnobs.at( i )->value() ) );
|
||||
|
||||
name = "pickup" + QString::number( i );
|
||||
_this.setAttribute( name, QString::number(
|
||||
m_pickupKnobs.at( i )->value() ) );
|
||||
|
||||
name = "length" + QString::number( i );
|
||||
_this.setAttribute( name, QString::number(
|
||||
m_lengthKnobs.at( i )->value() ) );
|
||||
|
||||
name = "pan" + QString::number( i );
|
||||
_this.setAttribute( name, QString::number(
|
||||
m_panKnobs.at( i )->value() ) );
|
||||
|
||||
name = "detune" + QString::number( i );
|
||||
_this.setAttribute( name, QString::number(
|
||||
m_detuneKnobs.at( i )->value() ) );
|
||||
|
||||
name = "slap" + QString::number( i );
|
||||
_this.setAttribute( name, QString::number(
|
||||
m_randomKnobs.at( i )->value() ) );
|
||||
|
||||
name = "impulse" + QString::number( i );
|
||||
_this.setAttribute( name, QString::number(
|
||||
m_impulses.at( i )->isChecked() ) );
|
||||
|
||||
QString sampleString;
|
||||
base64::encode(
|
||||
(const char *)m_editors.at( i )->getValues(),
|
||||
128 * sizeof(float), sampleString );
|
||||
name = "graph" + QString::number( i );
|
||||
_this.setAttribute( name, sampleString );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void vibed::loadSettings( const QDomElement & _this )
|
||||
{
|
||||
QString name;
|
||||
|
||||
for( Uint8 i = 0; i < 9; i++ )
|
||||
{
|
||||
name = "active" + QString::number( i );
|
||||
m_editors.at( i )->setOn( _this.attribute( name ).toInt() );
|
||||
|
||||
if( m_editors.at( i )->isOn() )
|
||||
{
|
||||
name = "volume" + QString::number( i );
|
||||
m_volumeKnobs.at( i )->setValue(
|
||||
_this.attribute( name ).toFloat() );
|
||||
|
||||
name = "stiffness" + QString::number( i );
|
||||
m_stiffnessKnobs.at( i )->setValue(
|
||||
_this.attribute( name ).toFloat() );
|
||||
|
||||
name = "pick" + QString::number( i );
|
||||
m_pickKnobs.at( i )->setValue(
|
||||
_this.attribute( name ).toFloat() );
|
||||
|
||||
name = "pickup" + QString::number( i );
|
||||
m_pickupKnobs.at( i )->setValue(
|
||||
_this.attribute( name ).toFloat() );
|
||||
|
||||
name = "length" + QString::number( i );
|
||||
m_lengthKnobs.at( i )->setValue(
|
||||
_this.attribute( name ).toFloat() );
|
||||
|
||||
name = "pan" + QString::number( i );
|
||||
m_panKnobs.at( i )->setValue(
|
||||
_this.attribute( name ).toFloat() );
|
||||
|
||||
name = "detune" + QString::number( i );
|
||||
m_detuneKnobs.at( i )->setValue(
|
||||
_this.attribute( name ).toFloat() );
|
||||
|
||||
name = "slap" + QString::number( i );
|
||||
m_randomKnobs.at( i )->setValue(
|
||||
_this.attribute( name ).toFloat() );
|
||||
|
||||
name = "impulse" + QString::number( i );
|
||||
m_impulses.at( i )->setChecked(
|
||||
_this.attribute( name ).toInt() );
|
||||
|
||||
name = "graph" + QString::number( i );
|
||||
float shape[128];
|
||||
int size = 0;
|
||||
QString sampleString = _this.attribute( name );
|
||||
char * dst = 0;
|
||||
base64::decode( sampleString, &dst, &size );
|
||||
memcpy( shape, dst, size );
|
||||
m_editors.at( i )->setValues( shape );
|
||||
}
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
QString vibed::nodeName( void ) const
|
||||
{
|
||||
return( vibedstrings_plugin_descriptor.name );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void vibed::playNote( notePlayHandle * _n )
|
||||
{
|
||||
if ( _n->totalFramesPlayed() == 0 )
|
||||
{
|
||||
float freq = getInstrumentTrack()->frequency( _n );
|
||||
|
||||
_n->m_pluginData = new stringContainer(
|
||||
freq,
|
||||
eng()->getMixer()->sampleRate(),
|
||||
m_sampleLength );
|
||||
|
||||
for( Uint8 i = 0; i < 9; i++ )
|
||||
{
|
||||
if( m_editors.at( i )->isOn() )
|
||||
{
|
||||
static_cast<stringContainer*>(
|
||||
_n->m_pluginData )->addString(
|
||||
m_harmonics.at( i )->getSelected(),
|
||||
m_pickKnobs.at( i )->value(),
|
||||
m_pickupKnobs.at( i )->value(),
|
||||
m_editors.at( i )->getValues(),
|
||||
m_randomKnobs.at( i )->value(),
|
||||
m_stiffnessKnobs.at( i )->value(),
|
||||
m_detuneKnobs.at( i )->value(),
|
||||
static_cast<int>(
|
||||
m_lengthKnobs.at( i )->value() ),
|
||||
m_impulses.at( i )->isChecked() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Uint32 frames = eng()->getMixer()->framesPerAudioBuffer();
|
||||
stringContainer * ps = static_cast<stringContainer *>(
|
||||
_n->m_pluginData );
|
||||
|
||||
sampleFrame * buf = bufferAllocator::alloc<sampleFrame>( frames );
|
||||
|
||||
float vol;
|
||||
float pan;
|
||||
float sample;
|
||||
Uint8 s;
|
||||
|
||||
for( Uint32 i = 0; i < frames; i++ )
|
||||
{
|
||||
buf[i][0] = 0.0f;
|
||||
buf[i][1] = 0.0f;
|
||||
s = 0;
|
||||
for( Uint8 string = 0; string < 9; string ++ )
|
||||
{
|
||||
if( m_editors.at( string )->isOn() )
|
||||
{
|
||||
vol = m_volumeKnobs.at(
|
||||
string )->value();
|
||||
pan = (
|
||||
m_panKnobs.at( string )->value() + 1 ) / 2.0;
|
||||
sample = ps->getStringSample( s );
|
||||
|
||||
buf[i][0] += pan * vol * sample;
|
||||
buf[i][1] += ( 1.0 - pan ) * vol * sample;
|
||||
s++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getInstrumentTrack()->processAudioBuffer( buf, frames, _n );
|
||||
|
||||
bufferAllocator::free( buf );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void vibed::deleteNotePluginData( notePlayHandle * _n )
|
||||
{
|
||||
delete static_cast<stringContainer *>( _n->m_pluginData );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void vibed::showString( Uint8 _string )
|
||||
{
|
||||
m_pickKnob->hide();
|
||||
m_pickupKnob->hide();
|
||||
m_stiffnessKnob->hide();
|
||||
m_volumeKnob->hide();
|
||||
m_panKnob->hide();
|
||||
m_detuneKnob->hide();
|
||||
m_randomKnob->hide();
|
||||
m_lengthKnob->hide();
|
||||
m_editor->hide();
|
||||
m_impulse->hide();
|
||||
m_harmonic->hide();
|
||||
|
||||
m_editors.at( _string )->show();
|
||||
m_volumeKnobs.at( _string )->show();
|
||||
m_stiffnessKnobs.at( _string )->show();
|
||||
m_pickKnobs.at( _string )->show();
|
||||
m_pickupKnobs.at( _string )->show();
|
||||
m_panKnobs.at( _string )->show();
|
||||
m_detuneKnobs.at( _string )->show();
|
||||
m_randomKnobs.at( _string )->show();
|
||||
m_lengthKnobs.at( _string )->show();
|
||||
m_impulses.at( _string )->show();
|
||||
m_impulses.at( _string )->update();
|
||||
m_harmonics.at( _string )->show();
|
||||
|
||||
m_pickKnob = m_pickKnobs.at( _string );
|
||||
m_pickupKnob = m_pickupKnobs.at( _string );
|
||||
m_stiffnessKnob = m_stiffnessKnobs.at( _string );
|
||||
m_volumeKnob = m_volumeKnobs.at( _string );
|
||||
m_panKnob = m_panKnobs.at( _string );
|
||||
m_detuneKnob = m_detuneKnobs.at( _string );
|
||||
m_randomKnob = m_randomKnobs.at( _string );
|
||||
m_lengthKnob = m_lengthKnobs.at( _string );
|
||||
m_editor = m_editors.at( _string );
|
||||
m_impulse = m_impulses.at( _string );
|
||||
m_harmonic = m_harmonics.at( _string );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void vibed::contextMenuEvent( QContextMenuEvent * )
|
||||
{
|
||||
QMenu contextMenu( this );
|
||||
#ifdef QT4
|
||||
contextMenu.setTitle( accessibleName() );
|
||||
#else
|
||||
QLabel * caption = new QLabel( "<font color=white><b>" +
|
||||
QString( "Vibed" ) + "</b></font>", this );
|
||||
caption->setPaletteBackgroundColor( QColor( 0, 0, 192 ) );
|
||||
caption->setAlignment( Qt::AlignCenter );
|
||||
contextMenu.addAction( caption );
|
||||
#endif
|
||||
contextMenu.addAction( embed::getIconPixmap( "help" ), tr( "&Help" ),
|
||||
this, SLOT( displayHelp() ) );
|
||||
contextMenu.exec( QCursor::pos() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void vibed::displayHelp( void )
|
||||
{
|
||||
#ifdef QT4
|
||||
QWhatsThis::showText( mapToGlobal( rect().bottomRight() ),
|
||||
whatsThis() );
|
||||
#else
|
||||
QWhatsThis::display( QWhatsThis::textFor( this ), mapToGlobal(
|
||||
rect().bottomRight() ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
// neccessary for getting instance out of shared lib
|
||||
plugin * lmms_plugin_main( void * _data )
|
||||
{
|
||||
return( new vibed( static_cast<instrumentTrack *>( _data ) ) );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#include "vibed.moc"
|
||||
|
||||
100
plugins/vibed/vibed.h
Normal file
100
plugins/vibed/vibed.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/* vibed_strings.h -
|
||||
*
|
||||
* Copyright (c) 2006 Danny McRae <khjklujn/at/yahoo/com>
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
#ifndef _VIBED_STRINGS_H
|
||||
#define _VIBED_STRINGS_H
|
||||
|
||||
#include <qptrlist.h>
|
||||
|
||||
#include "instrument.h"
|
||||
#include "sample_buffer.h"
|
||||
#include "graph.h"
|
||||
#include "pixmap_button.h"
|
||||
#include "buffer_allocator.h"
|
||||
#include "led_checkbox.h"
|
||||
#include "impulse_editor.h"
|
||||
#include "lcd_spinbox.h"
|
||||
#include "nine_button_selector.h"
|
||||
|
||||
class knob;
|
||||
class notePlayHandle;
|
||||
|
||||
|
||||
class vibed : public instrument
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
vibed( instrumentTrack * _channel_track );
|
||||
virtual ~vibed();
|
||||
|
||||
virtual void FASTCALL playNote( notePlayHandle * _n );
|
||||
virtual void FASTCALL deleteNotePluginData( notePlayHandle * _n );
|
||||
|
||||
|
||||
virtual void FASTCALL saveSettings( QDomDocument & _doc,
|
||||
QDomElement & _parent );
|
||||
virtual void FASTCALL loadSettings( const QDomElement & _this );
|
||||
|
||||
virtual QString nodeName( void ) const;
|
||||
|
||||
public slots:
|
||||
void showString( Uint8 _string );
|
||||
void contextMenuEvent( QContextMenuEvent * );
|
||||
void displayHelp( void );
|
||||
|
||||
private:
|
||||
QPtrList<knob> m_pickKnobs;
|
||||
QPtrList<knob> m_pickupKnobs;
|
||||
QPtrList<knob> m_stiffnessKnobs;
|
||||
QPtrList<knob> m_volumeKnobs;
|
||||
QPtrList<knob> m_panKnobs;
|
||||
QPtrList<knob> m_detuneKnobs;
|
||||
QPtrList<knob> m_randomKnobs;
|
||||
QPtrList<knob> m_lengthKnobs;
|
||||
QPtrList<impulseEditor> m_editors;
|
||||
QPtrList<ledCheckBox> m_impulses;
|
||||
QPtrList<nineButtonSelector> m_harmonics;
|
||||
|
||||
knob * m_pickKnob;
|
||||
knob * m_pickupKnob;
|
||||
knob * m_stiffnessKnob;
|
||||
knob * m_volumeKnob;
|
||||
knob * m_panKnob;
|
||||
knob * m_detuneKnob;
|
||||
knob * m_randomKnob;
|
||||
knob * m_lengthKnob;
|
||||
impulseEditor * m_editor;
|
||||
|
||||
nineButtonSelector * m_stringSelector;
|
||||
nineButtonSelector * m_harmonic;
|
||||
|
||||
ledCheckBox * m_impulse;
|
||||
|
||||
sampleBuffer * m_sampleBuffer;
|
||||
|
||||
int m_sampleLength;
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
#endif
|
||||
158
plugins/vibed/vibrating_string.cpp
Normal file
158
plugins/vibed/vibrating_string.cpp
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* vibrating_sring.h - model of a vibrating string lifted from pluckedSynth
|
||||
*
|
||||
* Copyright (c) 2006 Danny McRae <khjklujn/at/yahoo/com>
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
#include <math.h>
|
||||
|
||||
#include "vibrating_string.h"
|
||||
#include "templates.h"
|
||||
#include "interpolation.h"
|
||||
|
||||
|
||||
vibratingString::vibratingString( float _pitch,
|
||||
float _pick,
|
||||
float _pickup,
|
||||
float * _impulse,
|
||||
Uint32 _len,
|
||||
sample_rate_t _sample_rate,
|
||||
Uint8 _oversample,
|
||||
float _randomize,
|
||||
float _string_loss,
|
||||
float _detune,
|
||||
bool _state ):
|
||||
m_oversample( _oversample ),
|
||||
m_randomize( _randomize ),
|
||||
m_stringLoss( 1.0f - _string_loss ),
|
||||
m_state( 0.1f )
|
||||
{
|
||||
int string_length;
|
||||
|
||||
string_length = static_cast<int>( m_oversample *_sample_rate /
|
||||
_pitch ) + 1;
|
||||
string_length += static_cast<int>( string_length * -_detune );
|
||||
|
||||
int pick = static_cast<int>( ceil( string_length * _pick ) );
|
||||
|
||||
if( not _state )
|
||||
{
|
||||
m_impulse = bufferAllocator::alloc<float>( string_length );
|
||||
resample( _impulse, _len, string_length );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_impulse = bufferAllocator::alloc<float>( _len );
|
||||
for( Uint32 i = 0; i < _len; i++ )
|
||||
{
|
||||
m_impulse[i] = _impulse[i];
|
||||
}
|
||||
}
|
||||
|
||||
m_toBridge = vibratingString::initDelayLine( string_length, pick );
|
||||
m_fromBridge = vibratingString::initDelayLine( string_length, pick );
|
||||
|
||||
|
||||
vibratingString::setDelayLine( m_toBridge, pick,
|
||||
m_impulse, _len, 0.5f,
|
||||
_state );
|
||||
vibratingString::setDelayLine( m_fromBridge, pick,
|
||||
m_impulse, _len, 0.5f,
|
||||
_state);
|
||||
|
||||
m_choice = static_cast<int>( m_oversample *
|
||||
static_cast<float>( rand() ) / RAND_MAX );
|
||||
|
||||
m_pickupLoc = static_cast<int>( _pickup * string_length );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
vibratingString::delayLine * FASTCALL vibratingString::initDelayLine(
|
||||
int _len,
|
||||
int _pick )
|
||||
{
|
||||
delayLine * dl = new vibratingString::delayLine[_len];
|
||||
dl->length = _len;
|
||||
if( _len > 0 )
|
||||
{
|
||||
dl->data = new sample_t[_len];
|
||||
float r;
|
||||
float offset = 0.0f;
|
||||
for( int i = 0; i < dl->length; i++ )
|
||||
{
|
||||
r = static_cast<float>( rand() ) /
|
||||
RAND_MAX;
|
||||
offset = ( m_randomize / 2.0f -
|
||||
m_randomize ) * r;
|
||||
dl->data[i] = offset;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dl->data = NULL;
|
||||
}
|
||||
|
||||
dl->pointer = dl->data;
|
||||
dl->end = dl->data + _len - 1;
|
||||
|
||||
return( dl );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FASTCALL vibratingString::freeDelayLine( delayLine * _dl )
|
||||
{
|
||||
if( _dl && _dl->data )
|
||||
{
|
||||
delete[] _dl->data;
|
||||
}
|
||||
|
||||
_dl->data = NULL;
|
||||
delete[] _dl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FASTCALL vibratingString::resample( float *_src,
|
||||
f_cnt_t _src_frames,
|
||||
f_cnt_t _dst_frames )
|
||||
{
|
||||
for( f_cnt_t frame = 0; frame < _dst_frames; ++frame )
|
||||
{
|
||||
const float src_frame_float = frame *
|
||||
(float) _src_frames /
|
||||
_dst_frames;
|
||||
const float frac_pos = src_frame_float -
|
||||
static_cast<f_cnt_t>( src_frame_float );
|
||||
const f_cnt_t src_frame = tLimit<f_cnt_t>(
|
||||
static_cast<f_cnt_t>( src_frame_float ),
|
||||
1, _src_frames - 3 );
|
||||
m_impulse[frame] = cubicInterpolate(
|
||||
_src[src_frame - 1],
|
||||
_src[src_frame + 0],
|
||||
_src[src_frame + 1],
|
||||
_src[src_frame + 2],
|
||||
frac_pos );
|
||||
}
|
||||
}
|
||||
272
plugins/vibed/vibrating_string.h
Normal file
272
plugins/vibed/vibrating_string.h
Normal file
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* vibrating_string.h - model of a vibrating string lifted from pluckedSynth
|
||||
*
|
||||
* Copyright (c) 2006 Danny McRae <khjklujn/at/yahoo/com>
|
||||
*
|
||||
* 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., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
#ifndef _VIBRATING_STRING_H
|
||||
#define _VIBRATING_STRING_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "types.h"
|
||||
#include "buffer_allocator.h"
|
||||
|
||||
class vibratingString
|
||||
{
|
||||
public:
|
||||
vibratingString( float _pitch,
|
||||
float _pick,
|
||||
float _pickup,
|
||||
float * impluse,
|
||||
Uint32 _len,
|
||||
sample_rate_t _sample_rate,
|
||||
Uint8 _oversample,
|
||||
float _randomize,
|
||||
float _string_loss,
|
||||
float _detune,
|
||||
bool _state );
|
||||
|
||||
inline ~vibratingString( void )
|
||||
{
|
||||
bufferAllocator::free( m_impulse );
|
||||
vibratingString::freeDelayLine( m_fromBridge );
|
||||
vibratingString::freeDelayLine( m_toBridge );
|
||||
}
|
||||
|
||||
inline sample_t nextSample( void )
|
||||
{
|
||||
sample_t outsamp[m_oversample];
|
||||
sample_t ym0;
|
||||
sample_t ypM;
|
||||
for( Uint8 i = 0; i < m_oversample; i++)
|
||||
{
|
||||
// Output at pickup position
|
||||
outsamp[i] = fromBridgeAccess( m_fromBridge,
|
||||
m_pickupLoc );
|
||||
outsamp[i] += toBridgeAccess( m_toBridge,
|
||||
m_pickupLoc );
|
||||
|
||||
// Sample traveling into "bridge"
|
||||
ym0 = toBridgeAccess( m_toBridge, 1 );
|
||||
// Sample to "nut"
|
||||
ypM = fromBridgeAccess( m_fromBridge,
|
||||
m_fromBridge->length - 2 );
|
||||
|
||||
// String state update
|
||||
|
||||
// Decrement pointer and then update
|
||||
fromBridgeUpdate( m_fromBridge,
|
||||
-bridgeReflection( ym0 ) );
|
||||
// Update and then increment pointer
|
||||
toBridgeUpdate( m_toBridge, -ypM );
|
||||
}
|
||||
return( outsamp[m_choice] );
|
||||
}
|
||||
|
||||
private:
|
||||
struct delayLine
|
||||
{
|
||||
sample_t * data;
|
||||
int length;
|
||||
sample_t * pointer;
|
||||
sample_t * end;
|
||||
} ;
|
||||
|
||||
delayLine * m_fromBridge;
|
||||
delayLine * m_toBridge;
|
||||
int m_pickupLoc;
|
||||
Uint8 m_oversample;
|
||||
float m_randomize;
|
||||
float m_stringLoss;
|
||||
|
||||
float * m_impulse;
|
||||
int m_choice;
|
||||
float m_state;
|
||||
|
||||
delayLine * FASTCALL initDelayLine( int _len, int _pick );
|
||||
static void FASTCALL freeDelayLine( delayLine * _dl );
|
||||
void FASTCALL resample( float *_src,
|
||||
sample_rate_t _src_frames,
|
||||
sample_rate_t _dst_frames );
|
||||
|
||||
/* setDelayLine initializes the string with an impulse at the pick
|
||||
* position unless the impulse is longer than the string, in which
|
||||
* case the impulse gets truncated. */
|
||||
inline void setDelayLine( delayLine * _dl,
|
||||
int _pick,
|
||||
const float * _values,
|
||||
int _len,
|
||||
float _scale,
|
||||
bool _state )
|
||||
{
|
||||
float r;
|
||||
float offset;
|
||||
|
||||
if( not _state )
|
||||
{
|
||||
for( int i = 0; i < _pick; i++ )
|
||||
{
|
||||
r = static_cast<float>( rand() ) /
|
||||
RAND_MAX;
|
||||
offset = ( m_randomize / 2.0f -
|
||||
m_randomize ) * r;
|
||||
_dl->data[i] = _scale *
|
||||
_values[_dl->length - i] +
|
||||
offset;
|
||||
}
|
||||
for( int i = _pick; i < _dl->length; i++ )
|
||||
{
|
||||
r = static_cast<float>( rand() ) /
|
||||
RAND_MAX;
|
||||
offset = ( m_randomize / 2.0f -
|
||||
m_randomize ) * r;
|
||||
_dl->data[i] = _scale *
|
||||
_values[i - _pick] + offset ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( _len + _pick > _dl->length )
|
||||
{
|
||||
for( int i = _pick; i < _dl->length; i++ )
|
||||
{
|
||||
r = static_cast<float>( rand() ) /
|
||||
RAND_MAX;
|
||||
offset = ( m_randomize / 2.0f -
|
||||
m_randomize ) * r;
|
||||
_dl->data[i] = _scale *
|
||||
_values[i-_pick] +
|
||||
offset;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int i = 0; i < _len; i++ )
|
||||
{
|
||||
r = static_cast<float>( rand() ) /
|
||||
RAND_MAX;
|
||||
offset = ( m_randomize / 2.0f -
|
||||
m_randomize ) * r;
|
||||
_dl->data[i+_pick] = _scale *
|
||||
_values[i] +
|
||||
offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* toBridgeUpdate(dl, insamp);
|
||||
* Places "nut-reflected" sample from upper delay-line into
|
||||
* current lower delay-line pointer position (which represents
|
||||
* x = 0 position). The pointer is then incremented (i.e. the
|
||||
* wave travels one sample to the left), turning the previous
|
||||
* position into an "effective" x = L position for the next
|
||||
* iteration. */
|
||||
inline void toBridgeUpdate( delayLine * _dl, sample_t _insamp )
|
||||
{
|
||||
register sample_t * ptr = _dl->pointer;
|
||||
*ptr = _insamp * m_stringLoss;
|
||||
++ptr;
|
||||
if( ptr > _dl->end )
|
||||
{
|
||||
ptr = _dl->data;
|
||||
}
|
||||
_dl->pointer = ptr;
|
||||
}
|
||||
|
||||
/* fromBridgeUpdate(dl, insamp);
|
||||
* Decrements current upper delay-line pointer position (i.e.
|
||||
* the wave travels one sample to the right), moving it to the
|
||||
* "effective" x = 0 position for the next iteration. The
|
||||
* "bridge-reflected" sample from lower delay-line is then placed
|
||||
* into this position. */
|
||||
inline void fromBridgeUpdate( delayLine * _dl,
|
||||
sample_t _insamp )
|
||||
{
|
||||
register sample_t * ptr = _dl->pointer;
|
||||
--ptr;
|
||||
if( ptr < _dl->data )
|
||||
{
|
||||
ptr = _dl->end;
|
||||
}
|
||||
*ptr = _insamp * m_stringLoss;
|
||||
_dl->pointer = ptr;
|
||||
}
|
||||
|
||||
/* dlAccess(dl, position);
|
||||
* Returns sample "position" samples into delay-line's past.
|
||||
* Position "0" points to the most recently inserted sample. */
|
||||
static inline sample_t dlAccess( delayLine * _dl, int _position )
|
||||
{
|
||||
sample_t * outpos = _dl->pointer + _position;
|
||||
while( outpos < _dl->data )
|
||||
{
|
||||
outpos += _dl->length;
|
||||
}
|
||||
while( outpos > _dl->end )
|
||||
{
|
||||
outpos -= _dl->length;
|
||||
}
|
||||
return( *outpos );
|
||||
}
|
||||
|
||||
/*
|
||||
* Right-going delay line:
|
||||
* -->---->---->---
|
||||
* x=0
|
||||
* (pointer)
|
||||
* Left-going delay line:
|
||||
* --<----<----<---
|
||||
* x=0
|
||||
* (pointer)
|
||||
*/
|
||||
|
||||
/* fromBridgeAccess(dl, position);
|
||||
* Returns spatial sample at position "position", where position zero
|
||||
* is equal to the current upper delay-line pointer position (x = 0).
|
||||
* In a right-going delay-line, position increases to the right, and
|
||||
* delay increases to the right => left = past and right = future. */
|
||||
static inline sample_t fromBridgeAccess( delayLine * _dl,
|
||||
int _position )
|
||||
{
|
||||
return( dlAccess( _dl, _position ) );
|
||||
}
|
||||
|
||||
/* toBridgeAccess(dl, position);
|
||||
* Returns spatial sample at position "position", where position zero
|
||||
* is equal to the current lower delay-line pointer position (x = 0).
|
||||
* In a left-going delay-line, position increases to the right, and
|
||||
* delay DEcreases to the right => left = future and right = past. */
|
||||
static inline sample_t toBridgeAccess( delayLine * _dl, int _position )
|
||||
{
|
||||
return( dlAccess( _dl, _position ) );
|
||||
}
|
||||
|
||||
inline sample_t bridgeReflection( sample_t _insamp )
|
||||
{
|
||||
return( m_state = ( m_state + _insamp ) * 0.5 );
|
||||
}
|
||||
|
||||
} ;
|
||||
|
||||
#endif
|
||||
BIN
plugins/vibed/wavegraph4.png
Normal file
BIN
plugins/vibed/wavegraph4.png
Normal file
Binary file not shown.
@@ -472,9 +472,10 @@ void arpAndChordsTabWidget::processNote( notePlayHandle * _n )
|
||||
|
||||
// now follows code for arpeggio
|
||||
|
||||
if( _n->baseNote() == FALSE || m_arpDirectionBtnGrp->value() == OFF ||
|
||||
!m_arpGroupBox->isActive() ||
|
||||
( _n->released() && _n->releaseFramesDone() >=
|
||||
if( _n->baseNote() == FALSE ||
|
||||
( m_arpDirectionBtnGrp->value() + 1) == OFF ||
|
||||
!m_arpGroupBox->isActive() ||
|
||||
( _n->released() && _n->releaseFramesDone() >=
|
||||
_n->actualReleaseFramesToDo() ) )
|
||||
{
|
||||
return;
|
||||
@@ -483,13 +484,13 @@ void arpAndChordsTabWidget::processNote( notePlayHandle * _n )
|
||||
|
||||
const int selected_arp = m_arpComboBox->value();
|
||||
|
||||
constNotePlayHandleVector cnphv = notePlayHandle::nphsOfChannelTrack(
|
||||
_n->getInstrumentTrack() );
|
||||
constNotePlayHandleVector cnphv = notePlayHandle::nphsOfInstrumentTrack(
|
||||
_n->getInstrumentTrack() );
|
||||
if( m_arpModeComboBox->value() != FREE && cnphv.size() == 0 )
|
||||
{
|
||||
// maybe we're playing only a preset-preview-note?
|
||||
cnphv = presetPreviewPlayHandle::nphsOfChannelTrack(
|
||||
_n->getInstrumentTrack() );
|
||||
cnphv = presetPreviewPlayHandle::nphsOfInstrumentTrack(
|
||||
_n->getInstrumentTrack() );
|
||||
if( cnphv.size() == 0 )
|
||||
{
|
||||
// still nothing found here, so lets return
|
||||
@@ -654,7 +655,7 @@ void arpAndChordsTabWidget::saveSettings( QDomDocument & _doc,
|
||||
_this.setAttribute( "arprange", m_arpRangeKnob->value() );
|
||||
_this.setAttribute( "arptime", m_arpTimeKnob->value() );
|
||||
_this.setAttribute( "arpgate", m_arpGateKnob->value() );
|
||||
_this.setAttribute( "arpdir", m_arpDirectionBtnGrp->value() );
|
||||
_this.setAttribute( "arpdir", m_arpDirectionBtnGrp->value() + 1 );
|
||||
_this.setAttribute( "arpsyncmode",
|
||||
( int ) m_arpTimeKnob->getSyncMode() );
|
||||
|
||||
@@ -675,14 +676,14 @@ void arpAndChordsTabWidget::loadSettings( const QDomElement & _this )
|
||||
m_arpTimeKnob->setValue( _this.attribute( "arptime" ).toFloat() );
|
||||
m_arpGateKnob->setValue( _this.attribute( "arpgate" ).toFloat() );
|
||||
m_arpDirectionBtnGrp->setInitValue(
|
||||
_this.attribute( "arpdir" ).toInt() );
|
||||
_this.attribute( "arpdir" ).toInt() - 1 );
|
||||
m_arpTimeKnob->setSyncMode(
|
||||
( tempoSyncKnob::tempoSyncMode ) _this.attribute(
|
||||
"arpsyncmode" ).toInt() );
|
||||
|
||||
m_arpModeComboBox->setValue( _this.attribute( "arpmode" ).toInt() );
|
||||
|
||||
m_arpGroupBox->setState( m_arpDirectionBtnGrp->value() != OFF &&
|
||||
m_arpGroupBox->setState( _this.attribute( "arpdir" ).toInt() != OFF &&
|
||||
!_this.attribute( "arpdisabled" ).toInt() );
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "import_filter.h"
|
||||
#include "track_container.h"
|
||||
#include "project_journal.h"
|
||||
|
||||
#ifdef QT4
|
||||
|
||||
@@ -75,6 +76,10 @@ void importFilter::import( const QString & _file_to_import,
|
||||
#endif
|
||||
);
|
||||
|
||||
// do not record changes while importing files
|
||||
const bool j = _tc->eng()->getProjectJournal()->isJournalling();
|
||||
_tc->eng()->getProjectJournal()->setJournalling( FALSE );
|
||||
|
||||
for( vvector<plugin::descriptor>::iterator it = d.begin();
|
||||
it != d.end(); ++it )
|
||||
{
|
||||
@@ -93,6 +98,8 @@ void importFilter::import( const QString & _file_to_import,
|
||||
}
|
||||
}
|
||||
|
||||
_tc->eng()->getProjectJournal()->setJournalling( j );
|
||||
|
||||
delete[] s;
|
||||
|
||||
if( successful == FALSE )
|
||||
|
||||
@@ -348,7 +348,7 @@ int notePlayHandle::index( void ) const
|
||||
|
||||
|
||||
|
||||
constNotePlayHandleVector notePlayHandle::nphsOfChannelTrack(
|
||||
constNotePlayHandleVector notePlayHandle::nphsOfInstrumentTrack(
|
||||
const instrumentTrack * _it )
|
||||
{
|
||||
const playHandleVector & phv = _it->eng()->getMixer()->playHandles();
|
||||
|
||||
@@ -56,12 +56,15 @@ class previewTrackContainer : public trackContainer
|
||||
public:
|
||||
previewTrackContainer( engine * _engine ) :
|
||||
trackContainer( _engine ),
|
||||
m_previewChannelTrack( dynamic_cast<instrumentTrack *>(
|
||||
track::create( track::CHANNEL_TRACK,
|
||||
this ) )),
|
||||
m_previewInstrumentTrack( NULL ),
|
||||
m_previewNote( NULL ),
|
||||
m_dataMutex()
|
||||
{
|
||||
setJournalling( FALSE );
|
||||
m_previewInstrumentTrack = dynamic_cast<instrumentTrack *>(
|
||||
track::create( track::CHANNEL_TRACK,
|
||||
this ) );
|
||||
m_previewInstrumentTrack->setJournalling( FALSE );
|
||||
hide();
|
||||
}
|
||||
|
||||
@@ -81,9 +84,9 @@ public:
|
||||
return( "previewtc" );
|
||||
}
|
||||
|
||||
instrumentTrack * previewChannelTrack( void )
|
||||
instrumentTrack * previewInstrumentTrack( void )
|
||||
{
|
||||
return( m_previewChannelTrack );
|
||||
return( m_previewInstrumentTrack );
|
||||
}
|
||||
|
||||
notePlayHandle * previewNote( void )
|
||||
@@ -108,7 +111,7 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
instrumentTrack * m_previewChannelTrack;
|
||||
instrumentTrack * m_previewInstrumentTrack;
|
||||
notePlayHandle * m_previewNote;
|
||||
QMutex m_dataMutex;
|
||||
|
||||
@@ -141,21 +144,21 @@ presetPreviewPlayHandle::presetPreviewPlayHandle(
|
||||
|
||||
|
||||
multimediaProject mmp( _preset_file );
|
||||
previewTC()->previewChannelTrack()->loadTrackSpecificSettings(
|
||||
printf("load track sp\n");
|
||||
previewTC()->previewInstrumentTrack()->loadTrackSpecificSettings(
|
||||
mmp.content().firstChild().toElement() );
|
||||
printf("here\n");
|
||||
|
||||
// make sure, our preset-preview-track does not appear in any MIDI-
|
||||
// devices list, so just disable receiving/sending MIDI-events at all
|
||||
previewTC()->previewChannelTrack()->m_midiPort->setMode(
|
||||
previewTC()->previewInstrumentTrack()->m_midiPort->setMode(
|
||||
midiPort::DUMMY );
|
||||
|
||||
// create temporary note
|
||||
note n();
|
||||
// create note-play-handle for it
|
||||
m_previewNote = new notePlayHandle( previewTC()->previewChannelTrack(),
|
||||
0, ~0,
|
||||
m_previewNote = new notePlayHandle(
|
||||
previewTC()->previewInstrumentTrack(), 0, ~0,
|
||||
note( NULL, 0, 0, static_cast<tones>( A ),
|
||||
static_cast<octaves>( DEFAULT_OCTAVE-1 ), 100 ) );
|
||||
static_cast<octaves>( DEFAULT_OCTAVE - 1 ), 100 ) );
|
||||
|
||||
|
||||
previewTC()->setPreviewNote( m_previewNote );
|
||||
@@ -210,7 +213,7 @@ void presetPreviewPlayHandle::cleanUp( engine * _engine )
|
||||
|
||||
|
||||
|
||||
constNotePlayHandleVector presetPreviewPlayHandle::nphsOfChannelTrack(
|
||||
constNotePlayHandleVector presetPreviewPlayHandle::nphsOfInstrumentTrack(
|
||||
const instrumentTrack * _it )
|
||||
{
|
||||
constNotePlayHandleVector cnphv;
|
||||
|
||||
@@ -1368,7 +1368,8 @@ void songEditor::clearProject( void )
|
||||
|
||||
eng()->getProjectNotes()->clear();
|
||||
|
||||
eng()->getProjectJournal()->clear();
|
||||
eng()->getProjectJournal()->clearInvalidJournallingObjects();
|
||||
eng()->getProjectJournal()->clearJournal();
|
||||
|
||||
eng()->getProjectJournal()->setJournalling( TRUE );
|
||||
}
|
||||
|
||||
@@ -595,7 +595,7 @@ trackContentWidget::~trackContentWidget()
|
||||
|
||||
|
||||
|
||||
trackContentObject * FASTCALL trackContentWidget::getTCO( csize _tco_num )
|
||||
trackContentObject * trackContentWidget::getTCO( csize _tco_num )
|
||||
{
|
||||
if( _tco_num < m_trackContentObjects.size() )
|
||||
{
|
||||
@@ -618,8 +618,7 @@ csize trackContentWidget::numOfTCOs( void )
|
||||
|
||||
|
||||
|
||||
trackContentObject * FASTCALL trackContentWidget::addTCO(
|
||||
trackContentObject * _tco )
|
||||
trackContentObject * trackContentWidget::addTCO( trackContentObject * _tco )
|
||||
{
|
||||
QMap<QString, QVariant> map;
|
||||
map["id"] = _tco->id();
|
||||
@@ -639,7 +638,7 @@ trackContentObject * FASTCALL trackContentWidget::addTCO(
|
||||
|
||||
|
||||
|
||||
void FASTCALL trackContentWidget::removeTCO( csize _tco_num, bool _also_delete )
|
||||
void trackContentWidget::removeTCO( csize _tco_num, bool _also_delete )
|
||||
{
|
||||
removeTCO( getTCO( _tco_num ), _also_delete );
|
||||
}
|
||||
@@ -661,10 +660,12 @@ void trackContentWidget::removeTCO( trackContentObject * _tco,
|
||||
map["id"] = _tco->id();
|
||||
map["state"] = mmp.toString();
|
||||
addJournalEntry( journalEntry( REMOVE_TCO, map ) );
|
||||
|
||||
if( _also_delete )
|
||||
{
|
||||
delete _tco;
|
||||
}
|
||||
|
||||
m_trackContentObjects.erase( it );
|
||||
getTrack()->eng()->getSongEditor()->setModified();
|
||||
}
|
||||
@@ -873,15 +874,16 @@ void trackContentWidget::undoStep( journalEntry & _je )
|
||||
case ADD_TCO:
|
||||
{
|
||||
QMap<QString, QVariant> map = _je.data().toMap();
|
||||
journallingObject * jo =
|
||||
eng()->getProjectJournal()->getJournallingObject( map["id"].toInt() );
|
||||
assert( jo != NULL );
|
||||
trackContentObject * tco =
|
||||
dynamic_cast<trackContentObject *>(
|
||||
eng()->getProjectJournal()->getJournallingObject( map["id"].toInt() ) );
|
||||
assert( tco != NULL );
|
||||
multimediaProject mmp(
|
||||
multimediaProject::JOURNAL_DATA );
|
||||
jo->saveState( mmp, mmp.content() );
|
||||
tco->saveState( mmp, mmp.content() );
|
||||
map["state"] = mmp.toString();
|
||||
_je.data() = map;
|
||||
delete jo;
|
||||
tco->close();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1141,6 +1143,7 @@ void trackOperationsWidget::muteBtnRightClicked( void )
|
||||
|
||||
trackWidget::trackWidget( track * _track, QWidget * _parent ) :
|
||||
QWidget( _parent ),
|
||||
journallingObject( _track->eng() ),
|
||||
m_track( _track ),
|
||||
m_trackOperationsWidget( this ),
|
||||
m_trackSettingsWidget( this ),
|
||||
@@ -1232,6 +1235,46 @@ void trackWidget::changePosition( const midiTime & _new_pos )
|
||||
|
||||
|
||||
|
||||
void trackWidget::undoStep( journalEntry & _je )
|
||||
{
|
||||
saveJournallingState( FALSE );
|
||||
switch( _je.actionID() )
|
||||
{
|
||||
case MOVE_TRACK:
|
||||
{
|
||||
trackContainer * tc = m_track->getTrackContainer();
|
||||
if( _je.data().toInt() > 0 )
|
||||
{
|
||||
tc->moveTrackUp( m_track );
|
||||
}
|
||||
else
|
||||
{
|
||||
tc->moveTrackDown( m_track );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RESIZE_TRACK:
|
||||
setFixedHeight( tMax<int>( height() +
|
||||
_je.data().toInt(),
|
||||
MINIMAL_TRACK_HEIGHT ) );
|
||||
m_track->getTrackContainer()->realignTracks();
|
||||
break;
|
||||
}
|
||||
restoreJournallingState();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackWidget::redoStep( journalEntry & _je )
|
||||
{
|
||||
journalEntry je( _je.actionID(), -_je.data().toInt() );
|
||||
undoStep( je );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackWidget::dragEnterEvent( QDragEnterEvent * _dee )
|
||||
{
|
||||
stringPairDrag::processDragEnterEvent( _dee, "track_" +
|
||||
@@ -1320,6 +1363,7 @@ void trackWidget::mouseMoveEvent( QMouseEvent * _me )
|
||||
{
|
||||
tc->moveTrackDown( m_track );
|
||||
}
|
||||
addJournalEntry( journalEntry( MOVE_TRACK, _me->y() ) );
|
||||
}
|
||||
}
|
||||
else if( m_action == RESIZE_TRACK )
|
||||
@@ -1429,7 +1473,7 @@ track::~track()
|
||||
|
||||
|
||||
|
||||
track * FASTCALL track::create( trackTypes _tt, trackContainer * _tc )
|
||||
track * track::create( trackTypes _tt, trackContainer * _tc )
|
||||
{
|
||||
// while adding track, pause mixer for not getting into any trouble
|
||||
// because of track being not created completely so far
|
||||
@@ -1460,8 +1504,7 @@ track * FASTCALL track::create( trackTypes _tt, trackContainer * _tc )
|
||||
|
||||
|
||||
|
||||
track * FASTCALL track::create( const QDomElement & _this,
|
||||
trackContainer * _tc )
|
||||
track * track::create( const QDomElement & _this, trackContainer * _tc )
|
||||
{
|
||||
track * t = create( static_cast<trackTypes>( _this.attribute(
|
||||
"type" ).toInt() ), _tc );
|
||||
@@ -1472,7 +1515,7 @@ track * FASTCALL track::create( const QDomElement & _this,
|
||||
|
||||
|
||||
|
||||
track * FASTCALL track::clone( track * _track )
|
||||
track * track::clone( track * _track )
|
||||
{
|
||||
QDomDocument doc;
|
||||
QDomElement parent = doc.createElement( "clone" );
|
||||
@@ -1492,7 +1535,7 @@ tact track::length( void ) const
|
||||
|
||||
|
||||
|
||||
void FASTCALL track::saveSettings( QDomDocument & _doc, QDomElement & _this )
|
||||
void track::saveSettings( QDomDocument & _doc, QDomElement & _this )
|
||||
{
|
||||
csize num_of_tcos = getTrackContentWidget()->numOfTCOs();
|
||||
|
||||
@@ -1518,7 +1561,7 @@ void FASTCALL track::saveSettings( QDomDocument & _doc, QDomElement & _this )
|
||||
|
||||
|
||||
|
||||
void FASTCALL track::loadSettings( const QDomElement & _this )
|
||||
void track::loadSettings( const QDomElement & _this )
|
||||
{
|
||||
if( _this.attribute( "type" ).toInt() != type() )
|
||||
{
|
||||
@@ -1550,7 +1593,11 @@ void FASTCALL track::loadSettings( const QDomElement & _this )
|
||||
trackContentObject * tco = createTCO(
|
||||
midiTime( 0 ) );
|
||||
tco->restoreState( node.toElement() );
|
||||
getTrackContentWidget()->saveJournallingState(
|
||||
FALSE );
|
||||
addTCO( tco );
|
||||
getTrackContentWidget()->
|
||||
restoreJournallingState();
|
||||
}
|
||||
}
|
||||
node = node.nextSibling();
|
||||
@@ -1566,7 +1613,7 @@ void FASTCALL track::loadSettings( const QDomElement & _this )
|
||||
|
||||
|
||||
|
||||
trackContentObject * FASTCALL track::addTCO( trackContentObject * _tco )
|
||||
trackContentObject * track::addTCO( trackContentObject * _tco )
|
||||
{
|
||||
return( getTrackContentWidget()->addTCO( _tco ) );
|
||||
}
|
||||
@@ -1574,7 +1621,7 @@ trackContentObject * FASTCALL track::addTCO( trackContentObject * _tco )
|
||||
|
||||
|
||||
|
||||
void FASTCALL track::removeTCO( csize _tco_num )
|
||||
void track::removeTCO( csize _tco_num )
|
||||
{
|
||||
getTrackContentWidget()->removeTCO( _tco_num );
|
||||
}
|
||||
@@ -1590,7 +1637,7 @@ csize track::numOfTCOs( void )
|
||||
|
||||
|
||||
|
||||
trackContentObject * FASTCALL track::getTCO( csize _tco_num )
|
||||
trackContentObject * track::getTCO( csize _tco_num )
|
||||
{
|
||||
return( getTrackContentWidget()->getTCO( _tco_num ) );
|
||||
|
||||
@@ -1599,7 +1646,7 @@ trackContentObject * FASTCALL track::getTCO( csize _tco_num )
|
||||
|
||||
|
||||
|
||||
csize FASTCALL track::getTCONum( trackContentObject * _tco )
|
||||
csize track::getTCONum( trackContentObject * _tco )
|
||||
{
|
||||
for( csize i = 0; i < getTrackContentWidget()->numOfTCOs(); ++i )
|
||||
{
|
||||
@@ -1608,16 +1655,14 @@ csize FASTCALL track::getTCONum( trackContentObject * _tco )
|
||||
return( i );
|
||||
}
|
||||
}
|
||||
#ifdef LMMS_DEBUG
|
||||
qFatal( "track::getTCONum(...) -> _tco not found!\n" );
|
||||
#endif
|
||||
qWarning( "track::getTCONum(...) -> _tco not found!\n" );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void FASTCALL track::getTCOsInRange( vlist<trackContentObject *> & _tco_v,
|
||||
void track::getTCOsInRange( vlist<trackContentObject *> & _tco_v,
|
||||
const midiTime & _start,
|
||||
const midiTime & _end )
|
||||
{
|
||||
@@ -1655,7 +1700,7 @@ void FASTCALL track::getTCOsInRange( vlist<trackContentObject *> & _tco_v,
|
||||
|
||||
|
||||
|
||||
void FASTCALL track::swapPositionOfTCOs( csize _tco_num1, csize _tco_num2 )
|
||||
void track::swapPositionOfTCOs( csize _tco_num1, csize _tco_num2 )
|
||||
{
|
||||
getTrackContentWidget()->swapPositionOfTCOs( _tco_num1, _tco_num2 );
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
#include "import_filter.h"
|
||||
#include "instrument.h"
|
||||
#include "rubberband.h"
|
||||
#include "project_journal.h"
|
||||
|
||||
|
||||
|
||||
@@ -202,6 +203,10 @@ void trackContainer::cloneTrack( track * _track )
|
||||
|
||||
void trackContainer::addTrack( track * _track )
|
||||
{
|
||||
QMap<QString, QVariant> map;
|
||||
map["id"] = _track->id();
|
||||
addJournalEntry( journalEntry( ADD_TRACK, map ) );
|
||||
|
||||
m_trackWidgets.push_back( _track->getTrackWidget() );
|
||||
#ifndef QT4
|
||||
m_scrollArea->addChild( _track->getTrackWidget() );
|
||||
@@ -221,6 +226,13 @@ void trackContainer::removeTrack( track * _track )
|
||||
m_trackWidgets.end(), _track->getTrackWidget() );
|
||||
if( it != m_trackWidgets.end() )
|
||||
{
|
||||
QMap<QString, QVariant> map;
|
||||
multimediaProject mmp( multimediaProject::JOURNAL_DATA );
|
||||
_track->saveState( mmp, mmp.content() );
|
||||
map["id"] = _track->id();
|
||||
map["state"] = mmp.toString();
|
||||
addJournalEntry( journalEntry( REMOVE_TRACK, map ) );
|
||||
|
||||
eng()->getMixer()->pause();
|
||||
#ifndef QT4
|
||||
m_scrollArea->removeChild( _track->getTrackWidget() );
|
||||
@@ -417,6 +429,60 @@ void trackContainer::setPixelsPerTact( Uint16 _ppt )
|
||||
|
||||
|
||||
|
||||
void trackContainer::undoStep( journalEntry & _je )
|
||||
{
|
||||
saveJournallingState( FALSE );
|
||||
switch( _je.actionID() )
|
||||
{
|
||||
case ADD_TRACK:
|
||||
{
|
||||
QMap<QString, QVariant> map = _je.data().toMap();
|
||||
track * tr =
|
||||
dynamic_cast<track *>(
|
||||
eng()->getProjectJournal()->getJournallingObject( map["id"].toInt() ) );
|
||||
assert( tr != NULL );
|
||||
multimediaProject mmp(
|
||||
multimediaProject::JOURNAL_DATA );
|
||||
tr->saveState( mmp, mmp.content() );
|
||||
map["state"] = mmp.toString();
|
||||
_je.data() = map;
|
||||
removeTrack( tr );
|
||||
break;
|
||||
}
|
||||
|
||||
case REMOVE_TRACK:
|
||||
{
|
||||
multimediaProject mmp(
|
||||
_je.data().toMap()["state"].toString(), FALSE );
|
||||
track::create( mmp.content().firstChild().toElement(),
|
||||
this );
|
||||
break;
|
||||
}
|
||||
}
|
||||
restoreJournallingState();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainer::redoStep( journalEntry & _je )
|
||||
{
|
||||
switch( _je.actionID() )
|
||||
{
|
||||
case ADD_TRACK:
|
||||
case REMOVE_TRACK:
|
||||
_je.actionID() = ( _je.actionID() == ADD_TRACK ) ?
|
||||
REMOVE_TRACK : ADD_TRACK;
|
||||
undoStep( _je );
|
||||
_je.actionID() = ( _je.actionID() == ADD_TRACK ) ?
|
||||
REMOVE_TRACK : ADD_TRACK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainer::dragEnterEvent( QDragEnterEvent * _dee )
|
||||
{
|
||||
stringPairDrag::processDragEnterEvent( _dee,
|
||||
|
||||
@@ -69,6 +69,7 @@ journallingObject::~journallingObject()
|
||||
|
||||
void journallingObject::undo( void )
|
||||
{
|
||||
printf("undo: %d\n", id() );
|
||||
if( m_journalEntries.empty() == TRUE )
|
||||
{
|
||||
return;
|
||||
@@ -85,6 +86,7 @@ void journallingObject::undo( void )
|
||||
|
||||
void journallingObject::redo( void )
|
||||
{
|
||||
printf("undo: %d\n", id() );
|
||||
if( m_journalEntries.empty() == TRUE )
|
||||
{
|
||||
return;
|
||||
@@ -103,9 +105,9 @@ QDomElement journallingObject::saveState( QDomDocument & _doc,
|
||||
QDomElement & _parent )
|
||||
{
|
||||
QDomElement _this = _doc.createElement( nodeName() );
|
||||
_parent.appendChild( _this );
|
||||
saveSettings( _doc, _this );
|
||||
saveJournal( _doc, _this );
|
||||
_parent.appendChild( _this );
|
||||
return( _this );
|
||||
}
|
||||
|
||||
@@ -115,7 +117,11 @@ QDomElement journallingObject::saveState( QDomDocument & _doc,
|
||||
void journallingObject::restoreState( const QDomElement & _this )
|
||||
{
|
||||
saveJournallingState( FALSE );
|
||||
|
||||
// load actual settings
|
||||
loadSettings( _this );
|
||||
|
||||
// search for journal-node
|
||||
QDomNode node = _this.firstChild();
|
||||
while( !node.isNull() )
|
||||
{
|
||||
@@ -125,13 +131,14 @@ void journallingObject::restoreState( const QDomElement & _this )
|
||||
}
|
||||
node = node.nextSibling();
|
||||
}
|
||||
|
||||
restoreJournallingState();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void journallingObject::addJournalEntry( const journalEntry & _edit_step )
|
||||
void journallingObject::addJournalEntry( const journalEntry & _je )
|
||||
{
|
||||
if( !( eng() == NULL ||
|
||||
eng()->getProjectJournal()->isJournalling() == FALSE ||
|
||||
@@ -139,7 +146,7 @@ void journallingObject::addJournalEntry( const journalEntry & _edit_step )
|
||||
{
|
||||
m_journalEntries.erase( m_currentJournalEntry,
|
||||
m_journalEntries.end() );
|
||||
m_journalEntries.push_back( _edit_step );
|
||||
m_journalEntries.push_back( _je );
|
||||
m_currentJournalEntry = m_journalEntries.end();
|
||||
eng()->getProjectJournal()->journalEntryAdded( id() );
|
||||
}
|
||||
|
||||
@@ -152,10 +152,8 @@ multimediaProject::multimediaProject( const QString & _in_file_name,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QDomElement root = documentElement();
|
||||
m_type = type( root.attribute( "type" ) );
|
||||
|
||||
QDomNode node = root.firstChild();
|
||||
while( !node.isNull() )
|
||||
{
|
||||
@@ -308,7 +306,10 @@ QString multimediaProject::typeName( projectTypes _project_type )
|
||||
{
|
||||
if( _project_type >= UNKNOWN && _project_type < PROJ_TYPE_COUNT )
|
||||
{
|
||||
return( s_types[_project_type].m_name );
|
||||
return( s_types[_project_type].m_name
|
||||
#warning compat-code, remove in 0.3.0
|
||||
.section( ',', 0, 0 )
|
||||
);
|
||||
}
|
||||
return( s_types[UNKNOWN].m_name );
|
||||
}
|
||||
|
||||
@@ -80,6 +80,7 @@ void projectJournal::redo( void )
|
||||
|
||||
journallingObject * jo;
|
||||
|
||||
printf("%d\n", m_joIDs[*(m_currentJournalEntry+1)] );
|
||||
if( m_currentJournalEntry < m_journalEntries.end() &&
|
||||
( jo = m_joIDs[*m_currentJournalEntry++] ) != NULL )
|
||||
{
|
||||
@@ -97,7 +98,7 @@ void projectJournal::journalEntryAdded( const jo_id_t _id )
|
||||
m_journalEntries.push_back( _id );
|
||||
m_currentJournalEntry = m_journalEntries.end();
|
||||
eng()->getSongEditor()->setModified();
|
||||
printf("history size:%d\n", m_journalEntries.size());
|
||||
printf("history size: %d\n", m_journalEntries.size() );
|
||||
}
|
||||
|
||||
|
||||
@@ -122,7 +123,7 @@ jo_id_t projectJournal::allocID( journallingObject * _obj )
|
||||
|
||||
void projectJournal::reallocID( const jo_id_t _id, journallingObject * _obj )
|
||||
{
|
||||
//printf("realloc %d %d\n", _id, _obj);
|
||||
//printf("realloc %d %d\n", _id, _obj );
|
||||
if( m_joIDs.contains( _id ) )
|
||||
{
|
||||
m_joIDs[_id] = _obj;
|
||||
@@ -134,6 +135,7 @@ void projectJournal::reallocID( const jo_id_t _id, journallingObject * _obj )
|
||||
|
||||
void projectJournal::forgetAboutID( const jo_id_t _id )
|
||||
{
|
||||
printf("forget about %d\n", _id );
|
||||
journalEntryVector::iterator it;
|
||||
while( ( it = qFind( m_journalEntries.begin(), m_journalEntries.end(),
|
||||
_id ) ) != m_journalEntries.end() )
|
||||
@@ -150,12 +152,22 @@ void projectJournal::forgetAboutID( const jo_id_t _id )
|
||||
|
||||
|
||||
|
||||
void projectJournal::clear( void )
|
||||
void projectJournal::clearInvalidJournallingObjects( void )
|
||||
{
|
||||
while( m_joIDs.size() )
|
||||
vlist<journallingObject *>::const_iterator it;
|
||||
for( joIDMap::iterator it = m_joIDs.begin(); it != m_joIDs.end(); )
|
||||
{
|
||||
forgetAboutID( m_joIDs.keys().front() );
|
||||
if( it.data() == NULL )
|
||||
{
|
||||
forgetAboutID( it.key() );
|
||||
it = m_joIDs.begin();
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
//clearJournal();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -357,7 +357,8 @@ bool FASTCALL bbTrack::play( const midiTime & _start,
|
||||
{
|
||||
if( _tco_num >= 0 )
|
||||
{
|
||||
return( eng()->getBBEditor()->play( _start, _start_frame, _frames,
|
||||
return( eng()->getBBEditor()->play( _start, _start_frame,
|
||||
_frames,
|
||||
_frame_base,
|
||||
s_infoMap[this] ) );
|
||||
}
|
||||
@@ -424,7 +425,8 @@ void bbTrack::saveTrackSpecificSettings( QDomDocument & _doc,
|
||||
/* _this.setAttribute( "current", s_infoMap[this] ==
|
||||
eng()->getBBEditor()->currentBB() );*/
|
||||
if( s_infoMap[this] == 0 &&
|
||||
_this.parentNode().nodeName() != "clone" )
|
||||
_this.parentNode().nodeName() != "clone" &&
|
||||
_this.parentNode().nodeName() != "journaldata" )
|
||||
{
|
||||
eng()->getBBEditor()->saveState( _doc, _this );
|
||||
}
|
||||
|
||||
@@ -415,7 +415,9 @@ void instrumentTrack::saveSettingsBtnClicked( void )
|
||||
{
|
||||
multimediaProject mmp(
|
||||
multimediaProject::INSTRUMENT_TRACK_SETTINGS );
|
||||
saveTrackSpecificSettings( mmp, mmp.content() );
|
||||
QDomElement _this = mmp.createElement( nodeName() );
|
||||
saveTrackSpecificSettings( mmp, _this );
|
||||
mmp.content().appendChild( _this );
|
||||
#ifdef QT4
|
||||
mmp.writeFile( sfd.selectedFiles()[0] );
|
||||
#else
|
||||
|
||||
@@ -419,7 +419,7 @@ void pattern::saveSettings( QDomDocument & _doc, QDomElement & _this )
|
||||
// pattern, we must not store actual position, instead we store -1
|
||||
// which tells loadSettings() not to mess around with position
|
||||
if( _this.parentNode().nodeName() == "clipboard" ||
|
||||
_this.parentNode().nodeName() == "dnddata" )
|
||||
_this.parentNode().nodeName() == "dnddata" )
|
||||
{
|
||||
_this.setAttribute( "pos", -1 );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user