Skip to content

Commit 37e577f

Browse files
committed
9.0.0
1 parent 10fbd11 commit 37e577f

6 files changed

Lines changed: 80 additions & 166 deletions

File tree

‎CHANGELOG‎

Lines changed: 57 additions & 158 deletions
Original file line numberDiff line numberDiff line change
@@ -5,198 +5,97 @@ Release date:
55

66
New features:
77

8-
* Transpose a track or a column in all patterns at once
9-
- A "Transpose in all patterns" sub-menu on the Track and Column context
10-
menus, in one undo step, leaving the other tracks and columns alone
8+
Bug fixes:
119

12-
* Drum Synth V2
13-
- A second Drum Synth to build on. The original is untouched, so every kit in
14-
an existing project keeps playing exactly as it did
10+
Other:
1511

16-
- An amp envelope per voice: Attack, Hold, Decay and Curve, riding on top of
17-
what the voice already plays. Pull Hold down and the drum tightens
12+
9.0.0
13+
=====
1814

19-
- Crash and Ride fitted to a recording of the hardware: the crash opens out
20-
from its strike rather than being struck full, and the ride shimmers and
21-
darkens as it decays instead of ringing on unchanged
15+
Release date:
2216

23-
- Tune only ever brightens the cymbals now. Past about seventy per cent it
24-
used to push them against a fixed filter and darken them again
17+
Thu, 01 Oct 2026 23:21:48 +0300
2518

26-
- Snare and the three toms fitted to recordings of the hardware too: the toms
27-
are struck rather than only pitched, and the snare is a drum with snares on
28-
it rather than a burst of noise
19+
New features:
2920

30-
- Reverse Crash is the crash run backwards now, closing into its strike
31-
instead of swelling a cymbal that was already open
21+
* Sampler
22+
- Record straight onto a pad, with a metronome that counts in at the song's
23+
tempo; the take is trimmed to start on the downbeat
24+
- Recording works before the project is saved; the take is written out
25+
beside the project on save
26+
- Auto-trim and Crop to trim on a pad's context menu
27+
- Normalize brings a pad's peak to -6 dBFS without touching the file
28+
- The pad envelope is AHDSR with a Curve control; saved pads are unchanged
29+
- Chromatic pads can be put on any note, so a bass's four strings can sit a
30+
fourth apart instead of being stretched an octave each
31+
- A Mono switch per pad, beside Loop
32+
- Stereo level meters beside the wave view
33+
- An empty pad says how to fill it, and a take shows its length as it runs
3234

33-
- A Rim voice, on C#3, fitted to a recording of the hardware: a woody pitched
34-
click with a Click control for how much stick is in it
35+
* Drum Synth V2
36+
- A second Drum Synth to build on; the original is untouched
37+
- An AHDSR amp envelope per voice, off by default
38+
- Crash, Ride, Snare and the three toms fitted to recordings of the hardware
39+
- A Rim voice on C#3, with a Click control
40+
- Reverse Crash is the crash run backwards
41+
- Tune only ever brightens the cymbals
42+
- A waveform view with a playhead and the amp envelope laid over it
3543

36-
* Auto-trim and Crop to trim, on a pad's context menu
37-
- Auto-trim moves the markers in past the silence at either end, so it can be
38-
dragged back out. Crop to trim writes the trimmed range out as a new file
39-
and plays that, which is what shrinks an embedded project
44+
* The Drum Synths look like the rest of the application
45+
- Accent-coloured section headings, rounded pads, and the sections in
46+
columns beside the pads
4047

41-
* Recording straight into the Sampler
42-
- Sample an instrument in the room onto the selected pad: pick an input, hit
43-
Record, and what you played is on the pad when you stop
44-
- Works before the project has been saved. The recording is kept for the
45-
session and written out beside the project when you save it
48+
* Speech
49+
- Four more voices: Giant, Elder, Alien and Monster
50+
- Sing a line across a melody: a note played while another is held moves
51+
the pitch instead of speaking the next line, with Portamento between them
4652

47-
* Normalize, per Sampler pad
48-
- Brings a pad's loudest peak to -6 dBFS whatever it was recorded at,
49-
measured over the part the trims leave. A gain rather than an edit: the
50-
file is untouched
53+
* Gate, Bit Crusher, Flanger and Tremolo effects
54+
- Gate doubles as a downward expander, with Range and Hold
5155

52-
* A Curve control on the Sampler's pad envelope
53-
- The same bend the Synth's envelopes have, per pad, and the waveform view
54-
draws the shape the pad is actually played through
56+
* Sends per Sampler pad and per Drum Synth voice
57+
- A pad or voice reaches the send buses on its own, so one drum can sit in
58+
the reverb while the rest of the kit stays dry
59+
- One effects dialog per device, with Insert and Sends tabs
5560

5661
* Reference monitoring and headphone crossfeed
57-
- Reference plays the mix as another system would: Car, Club, Phone, Laptop,
58-
Hall, Boombox, Earbuds, TV or Nearfield
59-
- Crossfeed puts the far-ear arrival back for headphones
60-
- Neither is ever printed into a render
62+
- Reference plays the mix as Car, Club, Phone, Laptop, Hall, Boombox,
63+
Earbuds, TV or Nearfield; neither is ever printed into a render
6164

6265
* Analyse any audio file, and compare two
63-
- Tools => Analyse audio files... measures a WAV or FLAC the way the render
64-
report does, two files side by side
65-
- The chart draws both balances and the difference between them, which is
66-
the equalizer move from one to the other
67-
68-
* Send a Sampler pad or a Drum Synth voice on its own
69-
- A pad or voice reaches the global send buses independently of what its
70-
device sends, so one drum can sit in the reverb while the rest of the kit
71-
stays dry
72-
73-
* One effects dialog per device, with Insert and Sends tabs
74-
- A pad's or voice's routing is reachable from the same FX button its
75-
inserts are, and clicking a send row opens the effect on that bus
76-
77-
* Four more Speech voices: Giant, Elder, Alien and Monster
78-
- Monster growls: the folds double their period, which is a different thing
79-
from an unsteady voice and is what a roar actually is
80-
- The five voices that existed are untouched, so every saved device keeps
81-
the speaker it was written with
82-
83-
* Sing a Speech line across a melody
84-
- A note played while another is still held moves the pitch instead of
85-
fetching the next line, so one column can hold the line while another
86-
carries the tune
87-
- A Portamento control slides between those notes
88-
89-
* Four effects the rack was missing: Gate, Bit Crusher, Flanger and Tremolo
90-
- Gate doubles as a downward expander, with Range so a drum can be tightened
91-
rather than silenced, and Hold against chattering
92-
- Bit Crusher throws away word length and sample rate separately, and is
93-
deliberately not oversampled, because there the aliases are the point
94-
95-
* A waveform view on the Drum Synth V2, with a playhead
96-
- The selected voice drawn the way the Sampler draws a pad, its own insert
97-
effects included, with the amp envelope laid over it
98-
- Both it and the Sampler now read out how long the sound lasts and the
99-
tempo at which one hit fills a beat
100-
101-
* Sustain and Release on the Drum Synth V2's amp envelope
102-
- AHDSR rather than AHD. A device added now has the envelope switched off,
103-
sustain at full and the rest at their minimum, which is a voice exactly as
104-
V1 plays it rather than thirty-odd decibels close to it
105-
- Kits saved before the stage keep the envelope they were voiced against
106-
107-
* A Hold stage on the Sampler's pad envelope
108-
- AHDSR rather than ADSR, at zero by default, so every pad saved before it
109-
falls straight through into its decay exactly as it always did
110-
- The waveform view draws it, and the FX button on a pad takes the pad's own
111-
text colour so it stays readable on a bright accent
112-
113-
* A retriggered Drum Synth V2 voice hears its attack again
114-
- The level is walked to silence over two milliseconds before the new hit's
115-
attack, so a slow attack is slow on every hit and not only the first
66+
- Tools => Analyse audio files...; the chart draws the difference between
67+
the two balances
11668

117-
* The Drum Synths look like the rest of the application
118-
- Accent-coloured section headings instead of framed group boxes, rounded
119-
pads as the Sampler has, and every section a column beside the pads rather
120-
than a row of sliders under them
69+
* Transpose a track or a column in all patterns at once, in one undo step
70+
71+
* A Rate Divider of up to 64 on the Auto Panner
12172

12273
* The Synth's Multi Engine has a Noise tab of its own
123-
- Beside the oscillators rather than below them, since it is a noise source
124-
and not a fifth oscillator
12574

12675
* The oversampling is in the render's file name
127-
- Alongside the sample rate and the word length, so two renders that differ
128-
only in quality setting do not differ only in their timestamp
129-
130-
* A Rate Divider on the Auto Panner
131-
- Divides the rate by up to 64 in both modes, so a pan can sweep over several
132-
bars instead of stopping at one cycle per whole note
133-
134-
* Embedded samples are stored as FLAC
135-
- Lossless and about half the size. Re-saving an existing project converts
136-
what it carries
137-
138-
* Chromatic pads can be put on any note, from the pad's right-click menu
139-
- A pad plays at the rate it was recorded at on its own note and covers up to
140-
the next pad, so the four strings of a bass can sit a fourth apart instead
141-
of being stretched an octave each
142-
143-
* A metronome with a pre-count, in the Sampler
144-
- Counts you in at the song's tempo before a pad take and keeps clicking
145-
through it. Recording runs from the start, so nothing played early is lost,
146-
and the take is trimmed to begin on the downbeat
14776

148-
* The Sampler says what an empty pad is for, and how long a take is
149-
- "Record audio or assign a file" in the middle of an empty wave view, and a
150-
clock in its place while a recording runs
151-
152-
* A Mono switch per pad, beside Loop
153-
- Sums a stereo pad to one channel before it is panned, so it sits at a point
154-
in the image instead of keeping the width it was recorded with
155-
156-
* Stereo level meters beside the Sampler's wave view
157-
- The input while recording, the Sampler's own output the rest of the time
77+
* Embedded samples are stored as FLAC, about half the size
15878

15979
Bug fixes:
16080

161-
* A drum track can be transposed by naming it
162-
- The Track and Column transpositions left drum tracks alone, which only the
163-
pattern- and song-wide ones are meant to do
164-
165-
* A Sampler pad recording is no longer treated as a recording of the song
166-
- It used to take over the wave view under the editor, and the project saved a
167-
path to it -- one that stopped existing when the pad take was a temporary file
168-
169-
* Audio stream failures are reported instead of swallowed
170-
- RtAudio 6 reports them by return value rather than by throwing, so the
171-
handling written for RtAudio 5 never ran and a stream that would not open
172-
played or recorded silence without saying why
173-
174-
* Audio input and output devices are listed again
175-
- RtAudio 6 hands out device ids that are not 0, 1, 2, so enumerating by
176-
index found nothing. Settings had no devices to choose from
81+
* Audio devices are listed again with RtAudio 6, and stream failures are
82+
reported instead of playing or recording silence
17783

17884
* Unticking "Embed wave data" no longer loses the samples
179-
- A project whose pads came out of its own embedded data was saved pointing at
180-
a directory that stops existing when the application does. Those pads are
181-
now written out beside the project first
18285

183-
* Loading a project with a Drum Synth V2 in it no longer hangs
86+
* Track and Column transpositions transpose drum tracks too
18487

185-
* Stop the Stereo Field Meter and the RTA freezing on a silent device
88+
* The Stereo Field Meter and the RTA no longer freeze on a silent device
18689

187-
* The Auto Panner's rate readout now matches the rate it pans at, having read
188-
low by three and a half times in the middle of the control
90+
* The Auto Panner's rate readout matches the rate it pans at
18991

190-
* A Speech line no longer drawls over the rest of the song when nothing ends
191-
the note that speaks it
92+
* A Speech line no longer drawls on when nothing ends its note
19293

193-
* Speech's Line mode now fits a line to its note in a render as well as in
194-
playback, having always fallen back to Length when rendering
94+
* Speech's Line mode works in a render as well as in playback
19595

19696
Other:
19797

198-
* The Device Rack lists the tracks a Sub Mixer carries, and gives the track
199-
list more room before cutting it short
98+
* The Device Rack lists the tracks a Sub Mixer carries
20099

201100
8.0.0
202101
=====

‎CMakeLists.txt‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14)
33
project(Noteahead LANGUAGES CXX)
44

55
# Global version
6-
set(VERSION_MAJOR 8)
6+
set(VERSION_MAJOR 9)
77
set(VERSION_MINOR 0)
88
set(VERSION_PATCH 0)
99
set(VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}")

‎data/linux/noteahead.appdata.xml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@
1818
<url type="homepage">https://github.com/juzzlin/Noteahead</url>
1919
<update_contact>jussi.lind@iki.fi</update_contact>
2020
<releases>
21-
<release version="8.0.0" date="2026-09-13"></release>
21+
<release version="9.0.0" date="2026-10-01"></release>
2222
</releases>
2323
</component>

‎scripts/build-archive‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
git archive --format=tar.gz --prefix=noteahead-8.0.0/ HEAD > noteahead-8.0.0.tar.gz
1+
git archive --format=tar.gz --prefix=noteahead-9.0.0/ HEAD > noteahead-9.0.0.tar.gz

‎src/unit_tests/render_service_test/render_service_test.cpp‎

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "../../infra/audio/audio_engine.hpp"
1919
#include "../../infra/data_service.hpp"
2020

21+
#include <QCoreApplication>
2122
#include <QSignalSpy>
2223
#include <QTemporaryDir>
2324
#include <QTest>
@@ -28,6 +29,19 @@
2829

2930
namespace noteahead {
3031

32+
//! Blocks until the spy has seen `count` renders finish, however long they take.
33+
//!
34+
//! The worker hands its result back through the event loop, so waiting on the loop rather than on
35+
//! the clock follows the render itself: a CI machine still linking while the tests run has stalled a
36+
//! one-bar render for five seconds, and any timeout short enough to be useful can lose that race. A
37+
//! render that never finishes is left to ctest's own timeout.
38+
static void waitForRenders(const QSignalSpy & spy, qsizetype count)
39+
{
40+
while (spy.count() < count) {
41+
QCoreApplication::processEvents(QEventLoop::AllEvents | QEventLoop::WaitForMoreEvents);
42+
}
43+
}
44+
3145
//! A device that records the note length the render hands it, and nothing else.
3246
//!
3347
//! What it is for: a rendered song has to reach a device with the same note length a played one
@@ -174,7 +188,7 @@ void RenderServiceTest::test_renderIndividualTracks_shouldSkipNonInternalInstrum
174188
renderService.renderIndividualTracks(tempDir.path());
175189

176190
// Wait for it to finish.
177-
QVERIFY(spy.wait(5000));
191+
waitForRenders(spy, 1);
178192

179193
// Check that it finished successfully
180194
QCOMPARE(spy.at(0).at(0).toBool(), true);
@@ -247,7 +261,7 @@ void RenderServiceTest::test_renderIndividualTracks_shouldRestoreMixerState()
247261

248262
renderService.renderIndividualTracks(tempDir.path());
249263

250-
QVERIFY(spy.wait(5000));
264+
waitForRenders(spy, 1);
251265

252266
// Mixer state should be restored
253267
QCOMPARE(mixerService->isTrackSoloed(0), true);
@@ -285,7 +299,7 @@ void RenderServiceTest::test_renderMaster_secondRender_shouldStartFromZeroProgre
285299
QSignalSpy spy { &renderService, &RenderService::renderingFinished };
286300

287301
renderService.renderMaster(QDir { tempDir.path() }.filePath("first.flac"));
288-
QVERIFY(spy.wait(5000));
302+
waitForRenders(spy, 1);
289303
QCOMPARE(progressWhenBarAppears, 0.0);
290304

291305
// The first render left progress where it finished. Starting another one has to clear that, or
@@ -296,7 +310,7 @@ void RenderServiceTest::test_renderMaster_secondRender_shouldStartFromZeroProgre
296310
renderService.renderMaster(QDir { tempDir.path() }.filePath("second.flac"));
297311
QCOMPARE(progressWhenBarAppears, 0.0);
298312

299-
QVERIFY(spy.wait(5000));
313+
waitForRenders(spy, 2);
300314
}
301315

302316
void RenderServiceTest::test_renderMaster_shouldGiveTheDeviceTheNoteLength()
@@ -336,7 +350,7 @@ void RenderServiceTest::test_renderMaster_shouldGiveTheDeviceTheNoteLength()
336350
QVERIFY(tempDir.isValid());
337351
QSignalSpy spy { &renderService, &RenderService::renderingFinished };
338352
renderService.renderMaster(tempDir.filePath("render.flac"));
339-
QVERIFY(spy.wait(30000));
353+
waitForRenders(spy, 1);
340354
QVERIFY2(spy.at(0).at(0).toBool(), qPrintable(spy.at(0).at(1).toString()));
341355

342356
QVERIFY2(!probe->received().empty(), "the render never reached the device");

‎src/view/qml/Main.qml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import QtQuick.Controls.Universal 2.15
2020
import QtQuick.Dialogs
2121
import QtQuick.Layouts
2222
import Noteahead 1.0
23+
import "Components"
2324
import "Dialogs"
2425
import "Editor"
2526
import "ToolBar"

0 commit comments

Comments
 (0)