diff --git a/README.md b/README.md index 9b50bfa..526eb29 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,25 @@ # ChromaTracker -ChromaTracker is an (unfinshed) web-based [MOD](https://en.wikipedia.org/wiki/MOD_(file_format)) tracker, designed especially for phones and tablets. +ChromaTracker is an (unfinshed) web-based [MOD](https://en.wikipedia.org/wiki/MOD_(file_format)) music [tracker](https://en.wikipedia.org/wiki/Music_tracker), designed especially for phones and tablets. The design is primarily inspired by Alexander Zolotov's apps [SunVox](https://www.warmplace.ru/soft/sunvox/) and [PixiTracker](https://www.warmplace.ru/soft/pixitracker/), as well as [MilkyTracker](https://milkytracker.org/) and others. -Currently implemented: +Features: +- Supports mobile browsers and PWA installation + - Interface fits comfortably on a phone screen in portrait orientation - Custom MOD playback engine using Web Audio - Supports MOD extensions like extra channels, panning effects, and expanded frequency limits -- Pattern editor with touch keyboard, built-in effect documentation + - Supports almost all effects (only `E0x` and `EFx` are not supported) +- Pattern editor with touch keyboard, built-in effect documentation, cut/copy/paste - Sample editor with basic audio effects, 8-bit dithering, recording - Bird's-eye sequence overview (inspired by Renoise's Pattern Matrix) - Full undo support +- Persistent local file storage, import/export MOD/sample files - Render to WAV - A/V sync accounting for high-latency connections (e.g. Bluetooth) -- Persistent local file storage -- Supports mobile browsers and PWA installation You can try the current alpha build at [tracker.chroma.zone](https://tracker.chroma.zone/). On mobile devices it works best when it's installed as a [PWA](https://www.installpwa.com/from/tracker.chroma.zone). diff --git a/src/Playback.js b/src/Playback.js index 650b1d5..a3fbc70 100644 --- a/src/Playback.js +++ b/src/Playback.js @@ -898,7 +898,6 @@ export function getSamplePredictedPos(channel, time) { let timeDiff = time - channel.samplePredictTime if (timeDiff < 0) { return channel.samplePredictPos } let rate = periodToRate(channel.scheduledPeriod) - // TODO: use detune (arpeggios) let pos = Math.floor(channel.samplePredictPos + rate * baseRate * timeDiff) let {loopStart, loopEnd} = channel.sourceSample if (Sample.hasLoop(channel.sourceSample) && pos >= loopEnd) { diff --git a/src/file/Mod.js b/src/file/Mod.js index 27d981c..e458f93 100644 --- a/src/file/Mod.js +++ b/src/file/Mod.js @@ -47,7 +47,6 @@ export function read(buf) { /** @type {number} */ let numChannels = mod.defaultChannels let initials = asciiDecode.decode(new DataView(buf, 1080, 4)) - // TODO: support old 15-sample formats? let chanStr = initials.replace(/\D/g, '') // remove non-digits if (initials == 'OCTA' || initials == 'OKTA' || initials == 'CD81') { numChannels = 8 diff --git a/src/ui/WaveEdit.js b/src/ui/WaveEdit.js index 4b3753e..37a3d3a 100644 --- a/src/ui/WaveEdit.js +++ b/src/ui/WaveEdit.js @@ -179,7 +179,6 @@ export class WaveEdit { } if (sample.wave != this.viewSample?.wave) { - // TODO: async and only when visible! this.createSamplePreview(sample.wave) }