Skip to content
Browse files

update settingsui with scrollbar support.

update synthesis with pitch bend, envelopes, velocity, track volume, additional waveforms.
improve resolution of note on's and off's occurring during same frame.
add new test midis.
  • Loading branch information...
1 parent 63823a1 commit 1372bff7019e01f1626c72d8131f6ee3d60557a2 unknown committed Apr 9, 2012
View
BIN dalek/Assets/scrollbar.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
5 dalek/Source/CommonStyle.hx
@@ -36,8 +36,9 @@ class CommonStyle
settings = new SettingsUI(new Rectangle(0, 0, Lib.current.stage.stageWidth, Lib.current.stage.stageHeight),
rr, { up:styleUp, down:styleDown, over:styleUp, sizing:BSSPad(10, 10) }, cascade,
- {img:Assets.getBitmapData("assets/checkbox.png"), tw:16, th:16 },
- {img:Assets.getBitmapData("assets/slider.png"), tw:16, th:16, drawmode:SliderRepeat},
+ {bitmapdata:Assets.getBitmapData("assets/checkbox.png"), tile_w:16, tile_h:16 },
+ {bitmapdata:Assets.getBitmapData("assets/slider.png"), tile_w:16, tile_h:16, drawmode:SliderRepeat},
+ {bitmapdata:Assets.getBitmapData("assets/scrollbar.png"), tile_w:16, tile_h:16, drawmode:SliderRepeat},
"assets/sfx_test.mp3",buttonmanager);
}
View
10 dev/com/ludamix/triad/audio/MIDITuning.hx
@@ -8,6 +8,7 @@ interface MIDITuning
public function frequencyToMidiNote(frequency : Float) : Float;
public function midiNoteToFrequency(midiNote : Float) : Float;
+ public function midiNoteBentToFrequency(midiNote : Float, pitch_bend : Int) : Float;
}
@@ -20,8 +21,12 @@ class EvenTemperament implements MIDITuning
public var frequency : Array<Float>;
public var notename : Array<String>;
+ public var bend_semitones : Int;
+
public function new()
{
+ bend_semitones = 2;
+
var octave : Int = -1;
var semitone : Int = 0;
@@ -56,4 +61,9 @@ class EvenTemperament implements MIDITuning
return (Math.pow(2,(midiNote-69)/12)*440);
}
+ public inline function midiNoteBentToFrequency(midiNote : Float, pitch_bend : Int) : Float
+ {
+ return midiNoteToFrequency(midiNote+(pitch_bend)/8192*bend_semitones);
+ }
+
}
View
92 dev/com/ludamix/triad/audio/SMFParser.hx
@@ -6,10 +6,11 @@ import com.ludamix.triad.audio.Sequencer;
typedef SMFEvent = { tick:Int, type:Int, channel:Int, data:Dynamic };
-// TODO: Understand more events.
-
-// I am still not 100% sure about tempo changes, however they seem pretty stable in my current tests.
-// (I need to upgrade the synth quality to tell what's going on in the wing commander track)
+/* TODO: Understand more events.
+ TODO: Refactor into two parsers: one only gives the raw midi data, and the other cleans it up.
+ The goal should be to allow midi data to be streamed in. This also means changing my methods to be a bit
+ less "batch-y."
+ */
class SMFParser
{
@@ -25,19 +26,21 @@ class SMFParser
// Example in https://github.com/triplefox/triad/blob/master/examples/Source/SynthTest.hx
- public static function load(sequencer : Sequencer, bytes:ByteArray, ?filter = null) : Array<SequencerEvent>
+ public static function load(sequencer : Sequencer, bytes:ByteArray, ?filter = null,
+ ?init_filter = null) : Array<SequencerEvent>
{
if (filter == null) filter = defaultFilter;
+ if (init_filter == null) init_filter = defaultInit;
- var parser = new SMFParser(sequencer, bytes, filter);
+ var parser = new SMFParser(sequencer, bytes, filter, init_filter);
return parser.run();
}
- public function new(sequencer, ?bytes, ?filter)
- { this.sequencer = sequencer; this.bytes = bytes; this.filter = filter; }
+ public function new(sequencer, ?bytes, ?filter, ?init_filter)
+ { this.sequencer = sequencer; this.bytes = bytes; this.filter = filter; this.init_filter = init_filter; }
public var delta_time : Int;
public var time : Int;
@@ -49,7 +52,8 @@ class SMFParser
public var tempos : Array<{tick:Int,tempo:Int,bpm:Float,frames:Float}>;
public var tracks:Array<Array<SMFEvent>>;
public var events:Array<SequencerEvent>;
- public var filter : SMFEvent->Int->Float->Sequencer->SequencerEvent;
+ public var filter : SMFEvent->Int->Float->Sequencer->Dynamic->SequencerEvent;
+ public var init_filter : Void->Dynamic;
public var bytes : ByteArray;
public var sequencer : Sequencer;
@@ -97,6 +101,7 @@ class SMFParser
// do the final filtering.
tempos.sort(function(a, b) { return a.tick - b.tick; } );
+ var filter_persistent : Dynamic = init_filter();
for (track in tracks)
{
@@ -156,7 +161,7 @@ class SMFParser
frames += n.tick * tempos_past[tempos_past.length-1].frames;
}
- var result = filter(n, ticks, frames, sequencer);
+ var result = filter(n, ticks, frames, sequencer, filter_persistent);
if (result != null) events.push(result);
}
@@ -228,32 +233,75 @@ class SMFParser
public static inline var RPN_FINE_TUNE = 1;
public static inline var RPN_COARSE_TUNE = 2;
- public static function defaultFilter(smf:SMFEvent, ticks : Int, frames : Float, sequencer : Sequencer)
+ public static function defaultFilter(smf:SMFEvent, ticks : Int, frames : Float,
+ sequencer : Sequencer, persistent : Dynamic)
{
if (smf.type == NOTE_ON && smf.data.velocity == 0) // optimize - part of specced behavior
smf.type = NOTE_OFF;
switch(smf.type)
{
case NOTE_ON:
+ var unique_calc = smf.data.note + (smf.channel << 16);
+ var note_id = persistent.note_uniques.get(unique_calc);
return (new SequencerEvent(SequencerEvent.NOTE_ON,
- sequencer.waveLengthOfMidiNote(smf.data.note),
+ {note:sequencer.tuning.midiNoteToFrequency(smf.data.note),velocity:smf.data.velocity},
smf.channel,
- smf.data.note,
- Std.int(frames),
- smf.channel));
+ note_id,
+ Math.round(frames),
+ unique_calc));
case NOTE_OFF:
+ var unique_calc = smf.data.note + (smf.channel << 16);
+ var note_id = persistent.note_uniques.get(unique_calc);
+ persistent.id_ct++;
+ persistent.note_uniques.set(unique_calc, persistent.id_ct);
return (new SequencerEvent(SequencerEvent.NOTE_OFF,
- sequencer.waveLengthOfMidiNote(smf.data.note),
+ {note:sequencer.tuning.midiNoteToFrequency(smf.data.note),velocity:smf.data.velocity},
+ smf.channel,
+ note_id,
+ Math.round(frames),
+ unique_calc));
+ case PITCH_BEND:
+ return (new SequencerEvent(SequencerEvent.PITCH_BEND,
+ smf.data - 8192,
smf.channel,
- smf.data.note,
- Std.int(frames),
- smf.channel));
+ SequencerEvent.UNISON_ID,
+ Math.round(frames),
+ -1));
+ case CONTROL_CHANGE:
+ switch(smf.data.controller)
+ {
+ case CC_VOLUME:
+ return (new SequencerEvent(SequencerEvent.VOLUME,
+ smf.data.value/128,
+ smf.channel,
+ SequencerEvent.UNISON_ID,
+ Math.round(frames),
+ -1));
+ default:
+ //trace(["unimplemented cc", smf.data]);
+ return null;
+ }
default:
return null;
}
}
+ public static function defaultInit() : Dynamic
+ {
+ // we assign a unique id for each on-off pattern in each note and channel.
+ var t = { note_uniques:new IntHash<Int>(), id_ct : 0 };
+ for ( n in 0...128 )
+ {
+ for (c in 0...16)
+ {
+ t.note_uniques.set(n + (c << 16 ), t.id_ct);
+ t.id_ct++;
+ }
+ }
+ return t;
+ }
+
private function trackEvent(track : Array<SMFEvent>, tick : Int, type : Int, channel : Int, data : Dynamic)
{ track.push( { tick:tick, type:type, channel:channel, data:data }); }
@@ -357,10 +405,12 @@ class SMFParser
{note:bytes.readUnsignedByte(),pressure:bytes.readUnsignedByte()});
case CONTROL_CHANGE:
trackEvent(track, delta_time, status_base, channel,
- (bytes.readUnsignedByte()<<16) | bytes.readUnsignedByte());
+ { controller:bytes.readUnsignedByte(), value:bytes.readUnsignedByte() } );
case PITCH_BEND:
+ var lsb = bytes.readUnsignedByte();
+ var msb = bytes.readUnsignedByte();
trackEvent(track, delta_time, status_base, channel,
- bytes.readUnsignedByte() | (bytes.readUnsignedByte() << 8));
+ lsb | (msb << 7));
default:
throw "error: bad status("+Std.string(status)+") " + Std.string(status_base) +
" on channel "+Std.string(channel)+" at "+Std.string(bytes.position);
View
41 dev/com/ludamix/triad/audio/Sequencer.hx
@@ -29,13 +29,30 @@ class SequencerEvent
public static inline var NOTE_ON = 1;
public static inline var NOTE_OFF = 2;
+ public static inline var PITCH_BEND = 3; // normalized around 0
+ public static inline var VOLUME = 4;
}
class SequencerChannel
{
public var id : Int; public var outputs : Array<SoftSynth>;
+ // TODO: Allow channels to take ownership of a common pool of outputs, so that polyphony per channel is possible
+ // without using an excessive # of synth instances. (simple sharing scheme does not work with pitch bends)
+
+ // Here are all the situations I can think of:
+ //
+ // The channel reuses an existing synth.
+ // The channel broadcasts a unison event to the synths in use.
+ // The channel wants a new synth and it's available.
+ // The channel releases a synth.
+ //
+ // The issue that is causing trouble for me is that unison events should only apply to synths in use,
+ // but right now they apply to the pool of all used synths.
+ // One way to resolve this is to bulk up the channel state so that it contains all of the most recent unison events.
+ // Subsequently the synths use the channel state, not the synth state.
+
public function new(id, outputs)
{
this.id = id; this.outputs = outputs;
@@ -44,14 +61,14 @@ class SequencerChannel
public function priority(synth : SoftSynth) : Int
{
- return MathTools.bestOf(synth.events,
+ return MathTools.bestOf(synth.getEvents(),
function(inp) { return inp; },
function(a, b) { return a.priority > b.priority; }, {priority:-1} ).priority;
}
public function hasEvent(synth : SoftSynth, id : Int)
{
- return Lambda.exists(synth.events, function(ev) { return ev.id == id; } );
+ return Lambda.exists(synth.getEvents(), function(ev) { return ev.id == id; } );
}
public function pipe(ev : SequencerEvent)
@@ -114,7 +131,14 @@ class Sequencer
{ return (beat / (bpm / 60) * frameRate()); }
public inline function waveLength(frequency : Float) { return sampleRate() / frequency; }
- public inline function waveLengthOfMidiNote(note : Float) { return sampleRate() / tuning.midiNoteToFrequency(note); }
+ public inline function waveLengthOfBentNote(note : Float, pitch_bend : Int)
+ {
+ return waveLength(tuning.midiNoteBentToFrequency(note, pitch_bend));
+ }
+ public inline function waveLengthOfBentFrequency(frequency : Float, pitch_bend : Int)
+ {
+ return waveLengthOfBentNote(tuning.frequencyToMidiNote(frequency), pitch_bend);
+ }
// we should really be using a priority queue but for now I'll sort the array each time we add events...
public function pushEvent(event : SequencerEvent, ?now = true)
@@ -124,7 +148,7 @@ class Sequencer
event.frame + this.frame, event.priority));
else
events.push(event);
- events.sort(function(a, b) { return a.frame-b.frame; } );
+ sortEvents();
}
public function pushEvents(events : Array<SequencerEvent>, ?now = true)
@@ -139,7 +163,14 @@ class Sequencer
{
for (n in events) this.events.push(n);
}
- this.events.sort(function(a, b) { return a.frame-b.frame; } );
+ sortEvents();
+ }
+
+ public function sortEvents()
+ {
+ events.sort(function(a, b) {
+ if (a.frame == b.frame) { return (a.type - b.type); } // this favors note ends, lowering stuck likelihood
+ else return a.frame - b.frame; } );
}
public inline function addSynth(synth : SoftSynth) : SoftSynth
View
2 dev/com/ludamix/triad/audio/SoftSynth.hx
@@ -15,10 +15,10 @@ interface SoftSynth
public var buffer : Vector<Float>;
public var sequencer : Sequencer;
- public var events : Array<SequencerEvent>;
public function init(sequencer : Sequencer, buffersize : Int):Void;
public function write():Bool;
public function event(data : SequencerEvent, channel : SequencerChannel):Void;
+ public function getEvents():Array<SequencerEvent>;
}
View
217 dev/com/ludamix/triad/audio/TableSynth.hx
@@ -3,53 +3,201 @@ package com.ludamix.triad.audio;
import nme.Vector;
import com.ludamix.triad.audio.Sequencer;
-// TODO: Upgrade the synth. It will run a table of changes each frame for
-// pitch, vibrato, volume, waveform, support more waveforms, and more event types.
+class EventFollower
+{
+ public var event : SequencerEvent;
+ public var env_state : Int;
+ public var env_ptr : Int;
+
+ public function new(event : SequencerEvent)
+ {
+ this.event = event; env_state = 0; env_ptr = 0;
+ }
+}
class TableSynth implements SoftSynth
{
public var buffer : Vector<Float>;
- public var events : Array<SequencerEvent>;
+ public var events : Array<EventFollower>;
public var sequencer : Sequencer;
- public var wl : Int;
+ public var freq : Float;
public var pos : Int;
public var bufptr : Int;
+ public var master_volume : Float;
+ public var track_volume : Float;
+ public var velocity : Float;
+ public var velocity_mapping : Int;
+
+ public var pitch_bend : Int;
+
+ public static inline var VELOCITY_LINEAR = 0;
+ public static inline var VELOCITY_SQR = 1;
+ public static inline var VELOCITY_POW = 2;
+
+ public var attack_envelope : Array<Float>;
+ public var sustain_envelope : Array<Float>;
+ public var release_envelope : Array<Float>;
+
+ public var oscillator : Int;
+
+ public var pulsewidth : Float;
+
+ public static inline var ATTACK = 0;
+ public static inline var SUSTAIN = 1;
+ public static inline var RELEASE = 2;
+ public static inline var OFF = 3;
+
+ public static inline var PULSE = 0;
+ public static inline var SAW = 1;
+ public static inline var TRI = 2;
+
public function new()
{
- wl = 400;
+ freq = 440.;
pos = 0;
bufptr = 0;
+ master_volume = 0.1;
+ track_volume = 1.0;
+ velocity = 1.0;
+ velocity_mapping = VELOCITY_SQR;
+ pitch_bend = 0;
+
+ attack_envelope = [1.0];
+ sustain_envelope = [1.0];
+ release_envelope = [1.0];
+
+ oscillator = PULSE;
+ pulsewidth = 0.5;
+ }
+
+ public function interpretADSR(a : Float, d : Float, s : Float, r : Float)
+ {
+ var af = Math.ceil(sequencer.secondsToFrames(a));
+ var df = Math.ceil(sequencer.secondsToFrames(d));
+ var rf = Math.ceil(sequencer.secondsToFrames(r));
+
+ if (af == 0) af = 1;
+ if (df == 0) df = 1;
+ if (rf == 0) rf = 1;
+
+ attack_envelope = new Array<Float>();
+ for (n in 0...af)
+ attack_envelope.push(com.ludamix.triad.tools.MathTools.rescale(0,af,0.,1.0,n));
+ for (n in 0...df)
+ attack_envelope.push(com.ludamix.triad.tools.MathTools.rescale(0,df,s,1.0,df-n));
+ sustain_envelope = [s];
+ release_envelope = new Array<Float>();
+ for (n in 0...rf)
+ release_envelope.push(com.ludamix.triad.tools.MathTools.rescale(0,rf,0.,s,rf-n));
+
}
public function init(sequencer : Sequencer, buffersize : Int)
{
this.sequencer = sequencer;
this.buffer = new Vector(buffersize, true);
this.events = new Array();
+
+ interpretADSR(0.01,0.4,0.3,0.2);
+
}
- public function write()
+ public inline function velocityCurve()
{
- if (events.length < 1)
- return false;
- wl = Std.int(events[events.length-1].data);
- var hw = wl >> 1;
- for (i in 0 ... buffer.length>>1) {
- if (pos % wl < hw)
- {
- buffer[bufptr] = 0.1; // left
- buffer[bufptr+1] = 0.1; // right
- }
- else
+ switch(velocity_mapping)
+ {
+ case VELOCITY_LINEAR:
+ return velocity;
+ case VELOCITY_SQR:
+ return velocity * velocity;
+ case VELOCITY_POW:
+ return Math.pow(velocity, 1.0 - velocity);
+ default:
+ return velocity;
+ }
+ }
+
+ public function write()
+ {
+ while (events.length > 0 && events[events.length - 1].env_state == OFF) events.pop();
+ if (events.length < 1) return false;
+
+ var cur_event : EventFollower = events[events.length - 1];
+
+ freq = Std.int(cur_event.event.data.note);
+ var wl = Std.int(sequencer.waveLengthOfBentFrequency(freq, pitch_bend));
+
+ velocity = cur_event.event.data.velocity / 128;
+
+ // update envelopes and vol+envelope state
+ var envelopes = [attack_envelope, sustain_envelope, release_envelope];
+ var curval = master_volume * track_volume * velocityCurve() * envelopes[cur_event.env_state][cur_event.env_ptr];
+
+ // update pulsewidth and "halfway" point
+ pulsewidth += 0.01; if (pulsewidth > 2.0) pulsewidth = 0.;
+ var hw : Int;
+ if (pulsewidth > 1.0)
+ hw = Std.int(wl * (1.0 - (pulsewidth%1.0)));
+ else
+ hw = Std.int(wl * pulsewidth);
+
+ switch(oscillator)
+ {
+ case PULSE:
+ for (i in 0 ... buffer.length>>1) {
+ if (pos % wl < hw)
+ {
+ buffer[bufptr] = curval; // left
+ buffer[bufptr+1] = curval; // right
+ }
+ else
+ {
+ buffer[bufptr] = -curval; // left
+ buffer[bufptr+1] = -curval; // right
+ }
+ pos = (pos+2) % wl;
+ bufptr = (bufptr+2) % buffer.length;
+ }
+ case SAW:
+ var peak = 2 * curval;
+ var one_over_wl = peak / wl;
+ for (i in 0 ... buffer.length >> 1)
+ {
+ var sum = ((wl-(pos<<1)) % wl) * one_over_wl;
+ buffer[bufptr] = sum; // left
+ buffer[bufptr+1] = sum; // right
+ pos = (pos+2) % wl;
+ bufptr = (bufptr+2) % buffer.length;
+ }
+ case TRI:
+ var peak = curval;
+ var one_over_wl = peak / wl;
+ for (i in 0 ... buffer.length >> 1)
+ {
+ var sum = ((wl-(pos<<1)) % wl) * one_over_wl;
+ if (pos % wl >= hw)
+ {
+ sum = peak - sum;
+ }
+ buffer[bufptr] = sum; // left
+ buffer[bufptr+1] = sum; // right
+ pos = (pos+2) % wl;
+ bufptr = (bufptr+2) % buffer.length;
+ }
+ }
+
+ for (ev in events)
+ {
+ ev.env_ptr++;
+ if (ev.env_state!=OFF && ev.env_ptr >= envelopes[ev.env_state].length)
{
- buffer[bufptr] = 0.; // left
- buffer[bufptr+1] = 0.; // right
+ if (ev.env_state != SUSTAIN)
+ {ev.env_state += 1; }
+ ev.env_ptr = 0;
}
- pos = (pos+2) % wl;
- bufptr = (bufptr+2) % buffer.length;
}
return true;
}
@@ -59,10 +207,33 @@ class TableSynth implements SoftSynth
switch(ev.type)
{
case SequencerEvent.NOTE_ON:
- { events.push(ev); }
+ events.push(new EventFollower(ev));
case SequencerEvent.NOTE_OFF:
- {for (n in events.copy()) { if (n.id == ev.id) events.remove(n); }}
+ for (n in events)
+ {
+ if (n.event.id == ev.id)
+ {
+ if (release_envelope.length>0)
+ { if (n.env_state!=RELEASE) {n.env_state = RELEASE; n.env_ptr = 0;} }
+ else
+ n.env_state = OFF;
+ }
+ }
+ case SequencerEvent.PITCH_BEND:
+ pitch_bend = ev.data;
+ case SequencerEvent.VOLUME:
+ track_volume = ev.data;
+ }
+ }
+
+ public function getEvents()
+ {
+ var result = new Array<SequencerEvent>();
+ for ( n in events )
+ {
+ result.push(n.event);
}
+ return result;
}
}
View
6 dev/com/ludamix/triad/ui/SettingsUI.hx
@@ -26,14 +26,14 @@ class SettingsUI extends Sprite
var text : CascadingTextDef;
var button : { up:LabelRect9Style, down:LabelRect9Style, over:LabelRect9Style, sizing:ButtonSizingStrategy };
var frame : Rect9Template;
- var checkbox : {img:BitmapData,tw:Int,th:Int};
+ var checkbox : { bitmapdata:BitmapData, tile_w:Int, tile_h:Int };
var slider : ScrollableStyle;
var scrollbar : ScrollableStyle;
var preserve : Array<Dynamic>;
public function new(screenrect : Rectangle, frame : Rect9Template,
button : { up:LabelRect9Style, down:LabelRect9Style, over:LabelRect9Style, sizing:ButtonSizingStrategy },
- text : CascadingTextDef, checkbox : {img:BitmapData,tw:Int,th:Int},
+ text : CascadingTextDef, checkbox : {bitmapdata:BitmapData,tile_w:Int,tile_h:Int},
slider : ScrollableStyle, scrollbar : ScrollableStyle,
?testsound : String = null, ?bindings : ButtonManager = null, ?onClose : Void->Void = null,
?desiredW : Float=400, ?desiredH : Float=350)
@@ -136,7 +136,7 @@ class SettingsUI extends Sprite
public function addSlider(name : String, initVal : Float, initToggle : Bool, testsound : String)
{
- var check = Helpers.checkboxImage(checkbox.img, checkbox.tw, checkbox.th, initToggle, function(_) { } );
+ var check = Helpers.checkboxImage(checkbox.bitmapdata, checkbox.tile_w, checkbox.tile_h, initToggle, function(_) { } );
var widget = new HSlider6(this.slider, 120, initVal, null);
View
BIN examples/Assets/test_06.mid
Binary file not shown.
View
BIN examples/Assets/test_07.mid
Binary file not shown.
View
5 examples/Source/CommonStyle.hx
@@ -36,8 +36,9 @@ class CommonStyle
settings = new SettingsUI(new Rectangle(0, 0, Lib.current.stage.stageWidth, Lib.current.stage.stageHeight),
rr, { up:styleUp, down:styleDown, over:styleUp, sizing:BSSPad(10, 10) }, cascade,
- {img:Assets.getBitmapData("assets/checkbox.png"), tw:16, th:16 },
- {img:Assets.getBitmapData("assets/slider.png"), tw:16, th:16, drawmode:SliderRepeat},
+ {bitmapdata:Assets.getBitmapData("assets/checkbox.png"), tile_w:16, tile_h:16 },
+ {bitmapdata:Assets.getBitmapData("assets/slider.png"), tile_w:16, tile_h:16, drawmode:SliderRepeat},
+ {bitmapdata:Assets.getBitmapData("assets/scrollbar.png"), tile_w:16, tile_h:16, drawmode:SliderRepeat},
sound,buttonmanager);
}
View
43 examples/Source/GUITests.hx
@@ -44,6 +44,8 @@ class GUITests
buttonmanager = new ButtonManager(keys, 2);
Audio.init();
+ CommonStyle.init(buttonmanager,"assets/sfx_test.mp3");
+
var bg = new Sprite();
bg.graphics.beginFill(0xFF00FF,1.0);
bg.graphics.drawRect(0, 0, Lib.current.stage.stageWidth, Lib.current.stage.stageHeight);
@@ -98,37 +100,6 @@ class GUITests
));
moo.keys.slider.beginAnimating(150., SAForever(ADPingpong));
- // complex packh/packv mixture
-
- /*var moo = LayoutBuilder.create(0, 0, 800, 100,
- LDRect9(new Rect9(rr, 800, 200, true), LAC(0, 0), "panel",
- LDPackV(LPMFixed(LSPixel(10,true)),LAC(0,0),null,[
- LDPackH(LPMSpecified([LSRatio(1),LSRatio(2),LSPixel(10,true)]), LAC(0, 0), null,
- [LDRect9(new Rect9(rr, 50, 50, true), LAC(0, 0), null, LDEmpty),
- LDRect9(new Rect9(rr, 100, 50, true), LAC(0, 0), null, LDEmpty),
- LDRect9(new Rect9(rr, 70, 70, true), LAC(0, 0), null, LDEmpty)
- ]),
- LDPackH(LPMSpecified([LSRatio(1),LSRatio(2),LSPixel(10,true)]), LAC(0, 0), null,
- [LDRect9(new Rect9(rr, 50, 50, true), LAC(0, 0), null, LDEmpty),
- LDRect9(new Rect9(rr, 100, 50, true), LAC(0, 0), null, LDEmpty),
- LDRect9(new Rect9(rr, 70, 70, true), LAC(0, 0), null, LDEmpty)
- ]),
- ])));
- */
-
- // packtable
-
- /*
- var rList = new Array<LayoutDef>();
- for (n in 0...9)
- {
- rList.push(LDRect9(new Rect9(rr, Std.int(Math.random()*100+10), Std.int(Math.random()*100+10), true), LAC(0, 0), null, LDEmpty));
- }
- var moo = LayoutBuilder.create(0, 0, 500, 500,
- LDRect9(new Rect9(rr, 500, 500, true), LAC(0,0), null,
- LDPackTable(3, LPMFixed(LSPixel(10, true)), LPMFixed(LSPixel(10, true)), LAC(0, 0), null, rList)));
- */
-
Lib.current.stage.addChild(moo.sprite);
var testbmp = new Bitmap(new BitmapData(500, 500, false, Color.ARGB(0,0)));
@@ -140,15 +111,7 @@ class GUITests
sa.x = 100;
sa.y = 100;
- var ns = new SettingsUI(new Rectangle(0, 0, Lib.current.stage.stageWidth, Lib.current.stage.stageHeight),
- rr, { up:styleUp, down:styleDown, over:styleUp, sizing:BSSPad(10, 10) }, cascade,
- {img:Assets.getBitmapData("assets/checkbox.png"), tw:16, th:16 },
- {bitmapdata:Assets.getBitmapData("assets/slider.png"), tile_w:16, tile_h:16, drawmode:SliderRepeat},
- {bitmapdata:Assets.getBitmapData("assets/scrollbar.png"), tile_w:16, tile_h:16, drawmode:SliderRepeat},
- "assets/sfx_test.mp3",
- buttonmanager);
- Lib.current.stage.addChild(ns);
-
+ Lib.current.stage.addChild(CommonStyle.settings);
}
View
4 examples/Source/Main.hx
@@ -1,7 +1,7 @@
-typedef MyExample = GUITests;
+//typedef MyExample = GUITests;
//typedef MyExample = Blackjack;
//typedef MyExample = ASCIITest;
-//typedef MyExample = SynthTest;
+typedef MyExample = SynthTest;
//typedef MyExample = AssetReloading;
//typedef MyExample = Assistant;
View
18 examples/Source/SynthTest.hx
@@ -7,6 +7,7 @@ import nme.Lib;
import nme.media.Sound;
import com.ludamix.triad.audio.Sequencer;
import com.ludamix.triad.audio.Audio;
+import com.ludamix.triad.audio.SoftSynth;
import com.ludamix.triad.ui.SettingsUI;
// Not for use outside Flash.
@@ -21,10 +22,17 @@ class SynthTest
{
Audio.init({Volume:{vol:1.0,on:true}},true);
seq = new Sequencer();
- for (n in 0...64)
- seq.addSynth(new TableSynth());
- for (n in 0...16)
- seq.addChannel(seq.synths);
+ for (n in 0...11)
+ {
+ var set = new Array<SoftSynth>();
+ for (n in 0...8)
+ {
+ var synth = new TableSynth();
+ seq.addSynth(synth);
+ set.push(synth);
+ }
+ seq.addChannel(set);
+ }
//seq.pushEvent(new SequencerEvent(SequencerEvent.NOTE_ON, seq.waveLength(55.0), chan.id, 0, 0, 1));
//seq.pushEvent(new SequencerEvent(SequencerEvent.NOTE_ON, seq.waveLength(110.0), chan.id, 0, Std.int(seq.BPMToFrames(1,480.0)), 1));
@@ -35,7 +43,7 @@ class SynthTest
seq.play("synth", "Volume");
- events = SMFParser.load(seq, Assets.getBytes("assets/test_04.mid"));
+ events = SMFParser.load(seq, Assets.getBytes("assets/test_07.mid"));
for (n in events)
{
if (n.channel == 9 || n.channel == 11) // mute some instruments that translate poorly

0 comments on commit 1372bff

Please sign in to comment.
Something went wrong with that request. Please try again.