476

(164 replies, posted in Sinclair)

Excellent, thanks a lot! Good idea about caching the engine info, it was indeed getting super slow (several seconds on my T60, in fact).

477

(3 replies, posted in Sinclair)

Special offer... Vibratos, everyone, fresh vibratos... Now two channels with vibrato for the price of one!

Vibra is a ZX Spectrum beeper music engine with two tone channels and a 
dedicated noise channel. The tone channels support customizable vibrato and
slide effects. The vibrato effect has 7 speed settings, and 255 depth levels. 
Effective vibrato speed depends on the note frequency used. Tone channels are 
unbalanced, that means the second channel will play at approx. 80% volume of the
first channel.

The noise channel supports 255 pitch levels, and 127 volume levels. Noise 
generator is only updated if there is enough free CPU time, so data reads etc.
may affect the noise timbre.

The usual interrupting click drums are absent from this engine, as the available
effects should be sufficient to create drum sounds.

The engine reloads song data on the fly during playback, thus mitigating the
common problem of row transition noises for the most part.

Technical details:

- 12-bit note frequency dividers
- 8-bit noise pitch dividers
- 7-bit noise volume
- 3-bit vibrato speed (relative to note frequency)
- 8-bit vibrato depth
- 8-bit slide speed
- mixing at 7812.5 Hz

download
source (with more detailed comments this time)

No XM converter, sorry. I'll see about getting support for this into MDAL, but I'll probably need to make some adjustments first.

Anyway, aside from the vibrato technique (which is exactly as explained here, the most interesting part might be the use of two (fake) threads, based on Alone Coder's counter-skipping trick. The first updates the channel counters like usual, but also generates "tasks" depending on the state of the counters etc. Tasks are pushed to the stack (if nothing else needs to be done, an "idle" task is pushed). The second thread is switched to with a RET, so it'll execute whatever task is on top of the stack. This can be updating the vibrato/slides, updating the timer, or loading new data. If a given task cannot be completed within the available time frame, another task will be issued (eg. data loading can take up to 6 tasks depending on the situation).

The pitchable noise generator is based on Shiru's noise code, using my el-cheapo, HL-only XOR shift however. Noise quality is a bit weak due to the low mixing rate. There are also some other limitations, namely 1) invalid data can crash the engine and 2) vibratos may cause detune in some (rare) circumstances. Also, a general problem is that the vibrato speed is tied to the note frequency; this makes it impossible to have consistent vibratos across the note range.

Either way, this engine was a major pain in the a*** to write. Been busy with it for almost a whole week, and there's probably still a bug or two in there. Enjoy big_smile

Shiru wrote:

For oldest PCs that runs pure DOS, like XT/AT/386 maybe, the usual timed code approach may be viable, with a delay in the main loop that automatically gets adjusted at startup by measuring actual CPU speed.

There's a hacked(?) version of Music Construction Set that does exactly that. I can probably find it somewhere in my collection if you want to reverse-engineer that.

There's also 8088 MPH of course, had some great multi-channel msx in the last section. There's a detailed write-up on the engine tech, which includes a link to the source code of said engine.

Also, luckily archive.org has a copy of my lost pc speaker article. It's quite outdated now, but still there's a few items that are missing in your list wink

479

(7 replies, posted in Other Platforms)

Thanks Shiru, that'll come in handy some time.

480

(43 replies, posted in Atari)

Ha, I wish! I know only a few basic phrases in Polish, this one is courtesy of my friend Google Translate big_smile

481

(43 replies, posted in Atari)

Sillyventure 2k17 will have a GTIA compo again. Deadline is December 1st, and the usual rules apply.

I for one think it would be nice to have an original GTIA engine for this, not just the usual ports from Spectrum. XXL, czy możesz napisać nowy (oryginalny) engine dla GTIA?

482

(7 replies, posted in Other Platforms)

Radio-86RK does indeed sound scary.
Another thing that used to give me a good headache are those devices that output a fixed (preferably high-pitched) frequency (Channel F, or the Sharp Pocket thingies, for example). Thankfully, Zilog's squeeker algo is great at overriding those. Might be also a good candidate for Radio-86RK, since it doesn't seem to require exact timing.

I actually did write a sound routine for the VIC20 once. Couldn't find anything on how to create a 16-bit pointer, so I wrote some really ugly self-modifying code... then later, I looked it up and realized that I'd written it exactly like it's supposed to be done. I have to admit that kind of shaped my experience with MOS products big_smile Aside from VIC20, one machine I really want to tackle though is the Atari VCS, so I guess I'll have to wrap my head around 6502 (or 6507, in this case) at some point.

483

(135 replies, posted in Sinclair)

Damn, seems it's the week of failed experiments for me. In the last days, I tried to implement a very ambitious concept, basically an improved, multi-threaded Squeeker type engine that will calculate optimal wavelength ahead of time, so it's possible to mix two waves with 50% duty with just one output. After trying for 3 days to get it stable, I finally got fed up and put it aside.
So then today I tried to mix 15 square wave channels. Works, but it's... not great. Hear for yourselves.

Love the demo tune!

485

(7 replies, posted in Other Platforms)

From our forum member krüe: http://krue.net/stitch/ wink
Seriously, I think the Apple II has one of the worst 1-bit setups. Not being able to "set" the 1-bit state directly is a major hassle.
... hmm, one day when I have too much free time I might learn 65xx asm big_smile

Hah, that's a great idea!

487

(20 replies, posted in Sinclair)

PhaserX source
Proper editor is not public yet, for now there is support via MDAL reference compiler: https://github.com/utz82/MDAL

488

(20 replies, posted in Sinclair)

Results are in: http://events.retroscene.org/dh2017/ZX_Beeper_Music

Pity about temporal sad

489

(20 replies, posted in Sinclair)

Entries are online: http://events.retroscene.org/dh2017/ZX_Beeper_Music

490

(135 replies, posted in Sinclair)

Been thinking about the Earth Shaker method again. As far as I understand, it can essentially be implemented like this:

    di
    ld sp,#292        ;freq divider ch1
    ld bc,#1b7        ;freq divider ch2
;    ld hl,0            ;accu ch1
;    ld de,0            ;comparator/accu ch2

loop
    add hl,sp    ;11
    ex de,hl     ;4
    add hl,bc    ;11
    ex de,hl     ;4
    ld a,l       ;4    ;cp hl,de
    add a,e      ;4
    ld a,h       ;4
    adc a,d      ;4
    sbc a,a      ;4
    out (#fe),a  ;11
    ld a,0       ;7    ;timing
    jr loop      ;12
                 ;80

What I don't understand is how to reliably control the pitch. Usual note dividers often don't seem to work as intended. Is this just a limitation of the algorithm, or is do the dividers need to be adjusted depending on the desired harmonic relation?

Btw using the same divider for both channels with a slight offset gives a sweet phasing effect that I haven't come across earlier, see attachment.

Edit Also tried it with short (12-bit) counters. Turned out pretty lame (no nice detune fx possible either), and the time savings are minimal, just 8t. So it's not worth continuing in that direction, I think.

Hey, seems my featured article on PC Speaker on the 1-bit blog has disappeared! Anyway, good find, didn't know about those (except Turbo Outrun).
I wish I could wrap my head around x86 assembly, so I could disassemble some of the old multi-channel tools (especially Note Baron).

492

(164 replies, posted in Sinclair)

Garvalf, were you able to solve the issue? If not, you could try forcing gcc into 32-bit mode by adding -m32 to CXXFLAGS and LDFLAGS in the makefile.

493

(7 replies, posted in Sinclair)

Hell yeah! A great addition to the ZX beeper library. Excellent sound, very balanced. Squeeker method is fun, eh? Also great to see rlc (hl) being put to some good use. I'm always drooling over this instruction, but somehow can never find a good place to apply it... Another one that I'd love to abuse is rld/rrd. It has to be good for something...

494

(1 replies, posted in Sinclair)

Excellent. I think noise is another underexplored area in beeper music, we definately can do more with it.
Btw I have an algo that produces similar quality as the above, but doesn't need DE. I'm using this for the click drums in my recent engines.

     add hl,hl    ;11
     sbc a,a      ;4
     xor l        ;4
     ld l,a       ;4

Then afterwards, the usual cp with duty threshold. Some suitable seeds are 1, #1011, and #1237.

I also tried to do it with just 8-bit operations.

     ld a,d
     add a,e
     rlca
     ld d,a
     rr e

Seed DE with #21. Results are ok-ish, but not great. So I abandoned this idea for now.

495

(164 replies, posted in Sinclair)

Holy crap, 0.26 is awesome! Compiles out of the box, runs very smoothly, great fonts, and of course big thanks for adding Pytha. Only thing I need to do now is adding a black colour scheme for myself wink

Btw I added -O2 to CXXFLAGS. This reduces binary size by about 700 Kb and should make things run slightly faster. Didn't notice the difference though, as usage is already so much smoother than before.

496

(135 replies, posted in Sinclair)

Wow, didn't know about Bubble Dizzy either. Seems the music is mis-attributed to Dave Whittaker on WOS.

I agree, we need more vibrato on the beeper. Hey, I did post a vibrato routine earlier in this thread wink That one takes 96 cycles though, we definately need to do better. The triangle generator in it's current form wouldn't be usable as the algorithm produces an off-by-one error on the downward movement. But perhaps it's possible to derive something from that. I'll think more about it when I'm back from vacation.

Hmm, Sigma 7 has some brilliant glissandos as well. Wonder if those are hard-coded, or if there's a clever algorithm behind it.

497

(164 replies, posted in Sinclair)

That's great news, thanks a lot Shiru!
I've just returned from a very tiring weekend trip, will check out all the goodies tomorrow.

Hmm, I believe in most cases, especially with engines with few channels, there is actually at least one change every row. Also, as you know I always use a per-row speed setting. In that case it's something that should be handled on the tracker/converter end - if there is no change, simply increase the previous row length. Nevertheless, I'm sure there will be other cases where this "store only changes" approach is useful. In either way, it's a good reminder to keep thinking about song data structure. Got kind of sloppy with that myself. I'm perhaps too content with my current stack-read/skip-on-flag approach.

499

(164 replies, posted in Sinclair)

Then the JIT is probably not aware of that, and is still looking for the lib in the system directories. Not sure how to change that.

Yes, row 24 is the one where the pattern stops scrolling and the cursor will start to move upwards on key_up.

500

(164 replies, posted in Sinclair)

Compiles fine, and runs with JIT. Did you rebuild angelscript/lib by using the makefile in angelscript/projects/gnuc and sudo cp the resulting 3 files to your /lib system dir (or perhaps usr/local/lib under Ubuntu)?

File browser still doesn't traverse higher directories for me. The thing is that you cannot rely on the value of argv[0] under Linux. It might be a relative path to the exe, an absolute path, or something completely different. Under Debian, it's relative - if I start 1tracker from a higher directory with "./subdir/1tracker/1tracker", then I can traverse directories up to the level from where I started. The recommended, although by no means failsafe way on Linux is to read the process ID in /proc and derive the path from that. It's very messy though. I'd say for now just ignore the issue, and maybe later think about migrating to SDL2, which offers SDL_GetBasePath() for this purpose.

The fix for the display issue doesn't work, still blanks out when row < 24. What exactly is this construct supposed to do?

Btw it's a good idea to add a "clean" target to the makefile, like so:

.PHONY: clean
clean:
    rm *.o gme/*.o angelscript/angelscript_jit/*.o angelscript/scriptarray/*.o angelscript/scriptbuilder/*.o \
    angelscript/scriptstdstring/*.o angelscript/source/*.o