Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2.0.0 #21

Draft
wants to merge 31 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
fa1d5f9
Add drawBaseline option
ACrazyTown Nov 18, 2024
9fbaf2c
regen bitmap in draw()
ACrazyTown Nov 18, 2024
3ec2180
drawBaseline changes
ACrazyTown Nov 18, 2024
f4a0f10
fix no rendering
ACrazyTown Nov 18, 2024
4315ea2
baseline & resize fixes
ACrazyTown Nov 18, 2024
18db8db
Get rid of a lot of internal helpers
ACrazyTown Nov 20, 2024
cf6ff53
Change samplesPerPixel to int
ACrazyTown Nov 23, 2024
23ed078
log
ACrazyTown Nov 23, 2024
2142926
Fix wrong int min value
ACrazyTown Dec 4, 2024
b88c833
Add FlxWaveformBuffer
ACrazyTown Jan 3, 2025
989480e
A lot of docs
ACrazyTown Jan 3, 2025
1a66117
reorganize
ACrazyTown Jan 4, 2025
c8d96c0
WIP Sample graph
ACrazyTown Jan 10, 2025
44abbdc
Add RMS drawing, rendering improvements among other things
ACrazyTown Jan 11, 2025
79812dd
Remove leftover debugging...
ACrazyTown Jan 11, 2025
b4d933c
bars!
ACrazyTown Jan 14, 2025
95124d2
add drawDataDirty
ACrazyTown Jan 14, 2025
f961cdc
slight optimization
ACrazyTown Jan 14, 2025
c6022cc
WIP changelog/version bump
ACrazyTown Jan 14, 2025
b4f4528
tags as well
ACrazyTown Jan 14, 2025
92c0933
consistency
ACrazyTown Jan 14, 2025
ad23ecb
Update draw data in first draw call instead
ACrazyTown Jan 16, 2025
14e5570
Fixes for Flash
ACrazyTown Jan 16, 2025
c95221e
Solving more TODOs
ACrazyTown Jan 17, 2025
01a485b
Add WaveformDrawMode.SINGLE_CHANNEL
ACrazyTown Jan 18, 2025
602b4bd
Sync docs
ACrazyTown Jan 18, 2025
fa6dc87
Losing my mind
ACrazyTown Jan 19, 2025
d4aa228
docs
ACrazyTown Jan 19, 2025
434a8d3
Fixed a bug so revert old move code in sample
ACrazyTown Jan 19, 2025
acff497
rework sample
ACrazyTown Jan 19, 2025
acc5a01
match sample version with lib ver
ACrazyTown Jan 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"recommendations": [
"openfl.lime-vscode-extension",
"redhat.vscode-xml"
"redhat.vscode-xml",
"aaron-bond.better-comments"
]
}
18 changes: 16 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
## 1.2
## 1.3.0
- Added `waveformBarSize`, `waveformBarPadding`,
- Allows for more customizable waveform designs!
- Increase the bar size for more blockier waveforms which are also less expensive to compute
- Added `waveformRMSColor`, `waveformDrawRMS`
- Allows for visualizing the RMS (root mean square) of the audio data.
- The RMS represents the average/effective loudness of audio.
- Added `waveformDrawBaseline`
- Simply draws a line in the middle of the waveform to represent 0
- Added sample graph renderer when trying to view very low time ranges
- A seamless way of transitioning from the peak-based renderer and the graphed samples is planned for a future release.
- Added `SINGLE_CHANNEL(channel)` to `WaveformDrawMode` to allow drawing a single channel across the entire waveform area.
- A good chunk of code was refactored, so probably quite a few bug fixes?

## 1.2.0
- Added experimental HTML5 support
- 32bit audio now assumes it's stored as in Float32 format
- This is temporary until a proper way to differentiate the two is found. See https://github.com/ACrazyTown/flixel-waveform/issues/9
- Samples are now normalized in the range (-1, 1) instead of (0, 1)
- This is an internal change and should have no effect on anything public.

## 1.1
## 1.1.0
- Added support for 24bit audio
- Fix crashing when using mono sounds.

Expand Down
6 changes: 4 additions & 2 deletions haxelib.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
{
"name": "flixel-waveform",
"url": "https://github.com/ACrazyTown/flixel-waveform",
"description": "A `FlxWaveform` is an `FlxSprite` extension that provides a simple yet powerful API for drawing waveforms from audio data.",
"tags": ["audio", "waveform", "haxe", "haxeflixel", "flixel"],
"contributors": ["ACrazyTown"],
"classPath": "src",
"license": "MIT",
"version": "1.1.0",
"releasenote": "Support for 24bit audio; bugfixes; See CHANGELOG.md"
"version": "1.3.0",
"releasenote": "Stylization options, Graph samples, RMS; See CHANGELOG.md"
}
10 changes: 6 additions & 4 deletions samples/basic/Project.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<!-- _________________________ Application Settings _________________________ -->

<app title="flixel-waveform-sample" file="flixel-waveform-sample" main="Main" version="0.0.1" company="ACrazyTown" />
<app title="flixel-waveform-sample" file="flixel-waveform-sample" main="Main" version="1.3.0" company="ACrazyTown" />

<!--The flixel preloader is not accurate in Chrome. You can use it regularly if you embed the swf into a html file
or you can set the actual size of your file manually at "FlxPreloaderBase-onUpdate-bytesTotal"-->
Expand All @@ -16,7 +16,7 @@
<!-- ____________________________ Window Settings ___________________________ -->

<!--These window settings apply to all targets-->
<window width="400" height="400" fps="60" background="#000000" hardware="true" vsync="false" />
<window width="400" height="450" fps="60" background="#000000" hardware="true" vsync="false" />

<!--HTML5-specific-->
<window if="html5" resizable="true" />
Expand All @@ -31,7 +31,9 @@

<set name="BUILD_DIR" value="export" />
<source path="source" />
<assets path="assets" />

<assets path="assets" exclude="*.ogg" if="flash"/>
<assets path="assets" exclude="*.mp3" unless="flash"/>

<!-- _______________________________ Libraries ______________________________ -->

Expand All @@ -42,7 +44,7 @@
<!--<haxelib name="flixel-addons" />-->

<!--In case you want to use the ui package-->
<!--<haxelib name="flixel-ui" />-->
<haxelib name="flixel-ui" />

<!--In case you want to use nape with flixel-->
<!--<haxelib name="nape-haxe4" />-->
Expand Down
Binary file added samples/basic/assets/beeper.mp3
Binary file not shown.
43 changes: 43 additions & 0 deletions samples/basic/source/InitState.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package;

import flixel.FlxG;
import flixel.FlxState;
import flixel.text.FlxText;
import flixel.util.FlxTimer;

class InitState extends FlxState
{
override function create():Void
{
#if js
// On JavaScript/HTML5 we have to get a user interaction first
// otherwise we cannot create an AudioContext and the app
// will crash.
var text:FlxText = new FlxText(0, 0, 0, "Click to start", 32);
text.screenCenter();
add(text);
#else
// If on a different target we can just proceed as usual.
FlxG.switchState(PlayState.new);
#end
}

var switching:Bool = false;
override function update(elapsed:Float):Void
{
super.update(elapsed);

// Check for user interaction & switch state if we get one.
#if js
if (FlxG.mouse.justPressed && !switching)
{
switching = true;

// Wait a small amount of time before switching to the state
// to give time for the audio context to start and avoid a crash
// See: https://github.com/ACrazyTown/flixel-waveform/issues/8#issuecomment-2585483164
FlxTimer.wait(0.1, () -> FlxG.switchState(PlayState.new));
}
#end
}
}
2 changes: 1 addition & 1 deletion samples/basic/source/Main.hx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ class Main extends Sprite
public function new()
{
super();
addChild(new FlxGame(0, 0, PlayState));
addChild(new FlxGame(0, 0, InitState));
}
}
128 changes: 119 additions & 9 deletions samples/basic/source/PlayState.hx
Original file line number Diff line number Diff line change
@@ -1,31 +1,40 @@
package;

import flixel.addons.ui.FlxUIDropDownMenu;
import flixel.addons.ui.FlxUINumericStepper;
import flixel.addons.ui.FlxUICheckBox;
import flixel.text.FlxText;
import flixel.addons.ui.FlxUI;
import flixel.addons.ui.FlxUIState;
import flixel.ui.FlxButton;
import flixel.FlxG;
import flixel.FlxState;
import flixel.addons.display.waveform.FlxWaveform;

class PlayState extends FlxState
class PlayState extends FlxUIState
{
var ui:FlxUI;
var playPauseBtn:FlxButton;

var waveform:FlxWaveform;
var pixelsPerMs:Int;

override public function create():Void
{
super.create();

// Setup some stuff
#if debug
FlxG.console.registerEnum(WaveformDrawMode);
#end
FlxG.autoPause = false;
FlxG.camera.bgColor = 0xFF152E5A;

FlxG.sound.playMusic("assets/beeper.ogg");
FlxG.sound.music.stop();
FlxG.sound.music.looped = true;
FlxG.sound.music = FlxG.sound.load("assets/beeper" + #if flash ".mp3" #else ".ogg" #end, 1.0, true);

// NOTE: Due to a limitation, on HTML5
// you have to play the audio source
// before trying to make a waveform from it.
// See: https://github.com/ACrazyTown/flixel-waveform/issues/8
FlxG.sound.music.play(true);

// Check if bitmap max texture size is available.
Expand All @@ -46,18 +55,46 @@ class PlayState extends FlxState
#end

// Create a new FlxWaveform instance.
waveform = new FlxWaveform(0, 0, Std.int(FlxG.sound.music.length / pixelsPerMs), FlxG.height, 0xFF1C98E0);
waveform = new FlxWaveform(0, 50, Std.int(FlxG.sound.music.length / pixelsPerMs), FlxG.height - 50);

// Load data from the FlxSound so the waveform renderer can process it.
waveform.loadDataFromFlxSound(FlxG.sound.music);

// We set our draw range.
// When we leave it blank it'll default to a range from the beginning to the full length of the sound.
waveform.setDrawRange();

// We'll render both channels of the waveform seperately.
waveform.waveformDrawMode = SPLIT_CHANNELS;

// We don't have to manually generate the bitmap here, because `FlxWaveform.autoUpdateBitmap`
// is true by default, and changing the waveform draw mode above will trigger a redraw.
// waveform.generateWaveformBitmap();

// Set the color of the waveform.
waveform.waveformColor = 0xFF4577BE;

// Set the color of the waveform's background.
waveform.waveformBgColor = 0xFF253475;

// Toggle whether the RMS (root mean square) of the waveform should be drawn.
// The RMS represents the average/effective loudness of audio.
waveform.waveformDrawRMS = true;

// Set the color of the RMS waveform.
waveform.waveformRMSColor = 0xFF68C3FF;

// Whether the waveform baseline (line in the middle representing 0.0 of the sample) should be drawn
waveform.waveformDrawBaseline = true;

// For extra style points we can adjust the size and spacing of the waveform bars!
// As a demonstration, we'll set the size to 4px and the padding to 2px
waveform.waveformBarSize = 4;
waveform.waveformBarPadding = 2;

add(waveform);

setupUI();
}

override public function update(elapsed:Float):Void
Expand All @@ -66,13 +103,86 @@ class PlayState extends FlxState

if (FlxG.sound.music.playing)
{
// Make our camera follow the audio time.
camera.scroll.x = FlxG.sound.music.time / pixelsPerMs;
waveform.x = -(FlxG.sound.music.time / pixelsPerMs);
}

if (FlxG.keys.justPressed.SPACE)
playPause();
}

// --- Beyond this point is UI code you should not care about --

function setupUI():Void
{
ui = new FlxUI();
add(ui);

playPauseBtn = new FlxButton(5, 0, "Pause Music", playPause);
playPauseBtn.y = 5;
ui.add(playPauseBtn);

var drawRMSCheckbox:FlxUICheckBox = new FlxUICheckBox(10, 0, null, null, "Draw RMS");
drawRMSCheckbox.y = 30;
drawRMSCheckbox.checked = true;
drawRMSCheckbox.callback = () ->
{
waveform.waveformDrawRMS = !waveform.waveformDrawRMS;
};
ui.add(drawRMSCheckbox);

var paddingStepper:FlxUINumericStepper = new FlxUINumericStepper(drawRMSCheckbox.x + drawRMSCheckbox.width - 10, 0, 1, 0, 0, 100, 0);
paddingStepper.y = 10;
paddingStepper.value = waveform.waveformBarPadding;
paddingStepper.name = "s_padding";
ui.add(paddingStepper);
var paddingLabel:FlxText = new FlxText(0, 0, 0, "Bar Padding");
paddingLabel.x = paddingStepper.x + paddingStepper.width;
paddingLabel.y = paddingStepper.y;
ui.add(paddingLabel);

var sizeStepper:FlxUINumericStepper = new FlxUINumericStepper(drawRMSCheckbox.x + drawRMSCheckbox.width - 10, 0, 1, 1, 1, 100, 0);
sizeStepper.y = paddingStepper.y + 20;
sizeStepper.value = waveform.waveformBarSize;
sizeStepper.name = "s_size";
ui.add(sizeStepper);
var sizeLabel:FlxText = new FlxText(0, 0, 0, "Bar Size");
sizeLabel.x = sizeStepper.x + sizeStepper.width;
sizeLabel.y = sizeStepper.y;
ui.add(sizeLabel);

var drawModeLabel:FlxText = new FlxText(paddingLabel.x + 80, 5, 0, "Waveform Draw Mode");
ui.add(drawModeLabel);
var drawModeDropdown:FlxUIDropDownMenu = new FlxUIDropDownMenu(drawModeLabel.x, 20, FlxUIDropDownMenu.makeStrIdLabelArray(["Combined", "Split Channels", "Single Channel (Left)", "Single Channel (Right)"]), (select) ->
{
switch (select)
{
case "Combined": waveform.waveformDrawMode = COMBINED;
case "Split Channels": waveform.waveformDrawMode = SPLIT_CHANNELS;
case "Single Channel (Left)": waveform.waveformDrawMode = SINGLE_CHANNEL(0);
case "Single Channel (Right)": waveform.waveformDrawMode = SINGLE_CHANNEL(1);
}
});
drawModeDropdown.selectedLabel = "Split Channels";
ui.add(drawModeDropdown);
}

function playPause():Void
{
FlxG.sound.music.playing ? FlxG.sound.music.pause() : FlxG.sound.music.resume();
playPauseBtn.text = (FlxG.sound.music.playing ? "Pause" : "Play") + " Music";
}

override public function getEvent(id:String, sender:Dynamic, data:Dynamic, ?params:Array<Dynamic>):Void
{
super.getEvent(id, sender, data, params);

if (id == FlxUINumericStepper.CHANGE_EVENT && sender is FlxUINumericStepper)
{
FlxG.sound.music.playing ? FlxG.sound.music.pause() : FlxG.sound.music.resume();
var stepper:FlxUINumericStepper = cast sender;
if (stepper.name == "s_padding")
waveform.waveformBarPadding = Std.int(stepper.value);
else if (stepper.name == "s_size")
waveform.waveformBarSize = Std.int(stepper.value);
}
}
}
2 changes: 1 addition & 1 deletion src/flixel/addons/display/waveform/BytesExt.hx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class BytesExt
/**
* The minimum value of a signed 8bit integer.
*/
public static inline final INT8_MIN:Int = -127;
public static inline final INT8_MIN:Int = -128;

/**
* The maximum value of a signed 8bit integer.
Expand Down
Loading