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).
501 2017-06-30 15:00:14
Re: Multichannel/unusual PC speaker music (5 replies, posted in Other Platforms)
502 2017-06-30 14:47:34
Re: 1tracker v0.47 (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.
503 2017-06-30 14:36:20
Re: new engine: Squat (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...
504 2017-06-30 14:19:35
Re: Noise generator code (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.
505 2017-06-19 19:08:34
Re: 1tracker v0.47 (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
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.
506 2017-06-19 18:39:44
Re: next gen engine ideas (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 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.
507 2017-06-18 20:16:28
Re: 1tracker v0.47 (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.
508 2017-06-18 20:13:08
Re: Tutorial: How to Write a 1-Bit Music Routine (56 replies, posted in General Discussion)
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.
509 2017-06-14 10:23:35
Re: 1tracker v0.47 (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.
510 2017-06-14 09:06:04
Re: 1tracker v0.47 (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
511 2017-06-13 20:37:07
Re: 1tracker v0.47 (164 replies, posted in Sinclair)
Removing gui.h:246 solves the display issue. Not sure if it breaks something else though.
512 2017-06-13 19:19:42
Re: 1tracker v0.47 (164 replies, posted in Sinclair)
Filebrowser shows "./". Permissions shouldn't be an issue, at least not up to the user's home directory.
I'll do a bit of hunting for the editor bug as well. For now I found some suspicious looking code in song_editor.h:493
if(curSelectionWidth=module.columns)
Is that what you intended?
513 2017-06-13 16:08:11
Re: 1tracker v0.47 (164 replies, posted in Sinclair)
Great! Not that I'll be using the "chopped view" much, but it's always good to see ongoing development.
Alright, managed to compile it. The following changes were necessary:
makefile:1 CPPFLAGS=-I./angelscript -I./angelscript/include -I./angelscript_jit -I/usr/include/SDL -I/usr/include -std=c++11 -fpermissive -static
makefile:72 gme/Spc_Filter.o: gme/Spc_Filter.cpp
main.cpp:10 #include <dirent.h>
main.cpp:18 //remove
main.cpp:1200 mkdir(backupDirectory) -> mkdir(backupDirectory, S_IRWXU);
As usual, angelscript/lib needs to be rebuild and put into system lib directory. Used version 2.31.2, seems to work fine.
A couple of bugs:
internal filebrowser can only access files/directories inside the exec dir
pattern display will blank when using chopped view and current row < 24
514 2017-06-12 18:36:50
Re: ZX Spectrum Next (25 replies, posted in Sinclair)
Ah, didn't know that was him Been in touch with him via email in the meantime. Really looking forward to his sound driver. Might try to write a native tracker around it if I can find the time.
515 2017-06-12 18:31:51
Re: Tutorial: How to Write a 1-Bit Music Routine (56 replies, posted in General Discussion)
Part 12: Synthesizing Basic Waveforms: Rectangle, Triangle, Saw
In this chapter, I'm going to explain how to synthesize different waveforms without the use of samples or wavetables.
For generating waveforms other than a rectangle/pulse on a 1-bit output, we need to be able to output multiple volume levels. In part 10, we have looked at some methods for outputting PCM samples and wavetables. We concluded that in the 1-bit domain, time is directly related to volume. The longer we keep our 1-bit output "on" within a fixed-length frame, the higher the volume produced by the speaker cone will be. We can use this knowledge to write a very efficient rendering loop that will generate 8 volume levels with just 3 output commands:
calculate 3-bit volume
output (volume & 1) for t cycles
output (volume & 2) for 2t cycles
output (volume & 4) for 4t cycles and loop
As you can see, the trick here is to double the amount of cycles taken after each consecutive output command in the loop. An implementation of this for the ZX Spectrum beeper could look like this:
ld c,#fe
ld hl,0
ld de,frequency_divider
loop
add hl,de ;11 ;update frequency counter as usual
;... ;y ;do some magic to calculate 3-bit volume
;... ;z ;put it in bit 4-6 of register A
;so now bit 4 of A = volume & 1
out (c),a ;12: x+10+11+y+z=64 ;output to beeper
rrca ;4 ;now bit 4 of A = volume & 2
out (c),a ;12: 4+12=16 ;output
ds 4 ;16 ;timing
rrca ;4 ;now bit 4 of A = volume & 4
out (c),a ;12: 16+4+12=32 ;output
;... ;x ;update timer etc.
jp loop ;10 ;loop
If you count the cycles, you'll notice that this loop takes exactly 112 cycles. Which means we can easily add a second channel in the same manner, which brings the total cycle count to 224 - perfect for a ZX beeper routine. Side note: If necessary, you can cheat a little and reduce the 64-cycle output to 56 cycles, without much impact on the sound.
Anyway, we will use this framework as the basis for our waveform generation. So let's talk about the "magic" part.
The easiest of the basic waveforms is the saw wave. How so, you may ask? Well, the saw wave is actually right in front of your nose. Look at the first command in the sound loop - ADD HL,DE. Say we set the frequency divider in DE to 0x100. What happens to the H register? It is incremented by 1 each sound loop iteration, before wrapping around to 0 eventually. Ok, by now you might have guessed where this is going. If you haven't, then plot it out on a piece of paper - the value of H goes on the y-axis, and the number of loop iterations goes on the x-axis. Any questions? As you can see, our saw wave is actually generated for free while we update our frequency counter (thanks to Shiru for pointing this out to me). We just need to put it into A, and rotate once to get it into the right position.
add hl,de ;update frequency counter
ld a,h ;now 3-bit volume is in bit 5-7 of A
rrca ;now it's in bit 4-6
out (c),a ;output as above
...
Doing a triangle wave is a little more tricky. In fact, being the lousy mathematician that I am, it took me quite a while to figure this out. Ok, here's how it's done. We've already got the first half of our triangle wave done - it's the same as the saw wave. The second half is where the trouble starts - instead of increasing the volume further as we do for the saw wave, we want to decrease it again. So we could do something ugly like
add hl,de
ld a,h ;check if we've passed the half-way point of the saw
rla ;aka H >= 0x80
jp c,_invert_volume
...
reentry
rrca
out (c),a
...
jp loop
_invert_volume
;A = -H
There's a more elegant way that does the same thing without the need for conditional jumps.
add hl,de
ld a,h
rla
sbc a,a ;if h >= 0x80, A = 0xff, else A = 0
xor h ;0 xor H = H, 0xff xor H = -H - 1
out (c),a ;result is already in bit 4-6, no need to rotate
...
We can simply ignore the off-by-one error on H >= 0x80, since we don't care about the lower 4 bits anyway.
Last but not least, a word about rectangle waves. Of course, rectangle waves happen naturally on a 1-bit output, unless you force it to do something else. Which we are doing in this case, so how do we get things back to "normal"? Well, to get a square wave, we simply have to remove the XOR H from the previous code example. Which means that with just two bytes of self-modifying code, we can create a routine that will render saw, triangle, or square waves on demand:
add hl,de
ld a,h
rla
;saw | tri | rect
rra | sbc a,a | sbc a,a
rrca | xor h | nop
out (c),a
...
You'll notice that even with timer updates, register swapping, etc. you'll still have some free cycles left. Which should, of course, be put to some good use - see part 11 if you need some inspiration.
516 2017-06-11 14:12:10
Re: new engine: pytha (22 replies, posted in Sinclair)
You actually deserve some credit on this, since it was you who brought to my attention that we get a saw wave for free from the frequency calculation Triangle is basically the same thing, just have to negate the channel accu hi-byte if it's >#80.
517 2017-06-11 14:04:42
Re: next gen engine ideas (135 replies, posted in Sinclair)
Hmmf, tried mixing 4 triangle waves. It works, but it sounds rather awful. Not sure why that is. Of course, with the volume level reduced to two bits per channel, the sound will be a bit more distorted. But it shouldn't create all that high frequency fizz. And even when pairing notes (same note on ch1/2 and ch3/4), it's still much more noticable than in pytha, even though the core of this one is faster (200t vs 216t in pytha). Any ideas? Is it maybe because the level changes less often? It'd be great to be able to use the "one counter update per sound loop iteration" trick on this. Because then we could modulate our triangle osc with another triangle osc, which means we'd have primitive FM synthesis running. Well, guess I'm dreaming too much.
Edit: Attached proof-of-concept single channel FM example. It's incredibly simple, 2 ops only, so no change over time. Works but sounds terrible, unfortunately.
Edit2: Did some more tests. One thing I tried was to apply a simple low-pass filter (actual_vol = (last_vol + current_vol) / 2) - no luck. Also tried a very fast routine, mixing 2 triangles in 112t. Even that creates significant parasite tone. So either there's something wrong with my algorithm, or 4 levels is simply not enough to render a passable triangle wave.
Edit3: Sure enough, I can reproduce the effect with a hand-drawn sample in Milkytracker. So the noise is definately caused by the reduced number of volume levels. Damn! I'm afraid that means FM synthesis just isn't going to happen, at least not on 48K.
518 2017-06-10 10:08:16
Re: new engine: pytha (22 replies, posted in Sinclair)
Cheers guys
Ok, here's an updated version in action: http://irrlichtproject.de/transfer/pytha-demo2.mp3
While still not clean (of course, it's beeper, damnit ), there's a slight but noticable improvement I'd say. Btw just to be clear, both recordings are 100% raw, no EQ or filtering applied.
519 2017-06-09 21:42:12
Re: new engine: pytha (22 replies, posted in Sinclair)
Ok, here's a hardware recording: http://irrlichtproject.de/transfer/pytha-demo.mp3
Could be cleaner, yes, but still it's nothing a little equalizing can't solve, I think. I'll have another go at shaving off a few more cycles, though, which should push that HF noise a bit more towards the inaudible range.
520 2017-06-09 19:35:37
Re: new engine: pytha (22 replies, posted in Sinclair)
Hmm, that shouldn't be the case. There is some noise on the pure triangle, and the modulation effect has a pretty sharp sound, but it should be tolerable (unless my ears are getting bad). Are you running on hardware or Fuse emulator? Most other emulators have problems with this type of fast-switching synthesis.
Border masking would cost a lot of cycles, so unfortunately it's pretty much impossible.
521 2017-06-09 17:24:25
Re: new engine: pytha (22 replies, posted in Sinclair)
Whoops, just noticed that I miscalculated the timing, 220 cycles instead of 224. Got a version which runs in 216, but the improvement to the sound is barely noticable so I'll leave the engine as it is for the time being.
522 2017-06-09 11:50:14
Topic: new engine: pytha (22 replies, posted in Sinclair)
Yep, still totally retired from making new beeper engines... ah, damnit.
Alright then, say hello to Pytha, the first beeper engine that can generate triangle waves in realtime, without wavetable lookup. Just two channels, both of them do the same thing. In addition to triangle waves, there's also saw and pulse (rectangle). There's also an LFO-controlled modulator thingy, which does some weird sweep/resonant filter fx. With the LFO turned off, the modulator can also be used to set the duty cycle for the pulse waveform. All the base waveforms can be turned into noise as well. And of course, there's the usual click drums, with variable starting pitch and slide speed for the kick, and variable volume for noise. The LFO runs at a fixed rate. Tried making that variable, but unfortunately it creates too much noise. It'd also be nice to shave a few cycles from the synth loop for better sound. There's actually 10 cycles wasted on timing, however they are in a really bad spot so it's hard to reduce them to 2.
Anyway, won't make an XM converter for this, for obvious reasons. Got a working MDAL config for it, though, just need to polish up a few things on that. For now, the source code is in the github repo, as usual. Short demo tune is attached.
523 2017-06-09 11:23:44
Re: DiHalt 2017 (July 1-2) (20 replies, posted in Sinclair)
Not sure if I'll be able to make it. But I'll try.
524 2017-06-07 17:56:00
Re: next gen engine ideas (135 replies, posted in Sinclair)
Another 1-bit puzzle cracked: How to generate a triangle wave without wavetable lookup. There are some killer modulation effects that you can do with this as well, but I still need to find a few free t-states in order to implement those for 2 channels.
Edit: Ok, got it. Here's a shorter and faster version, 11 t-states free which will be enough to pull of the modulation effects.
sloop
add hl,de ;11
ld a,0 ;7 ;timing
nop ;4 ;timing
ld a,h ;4
rlca ;4
sbc a,a ;4
xor h ;4
rrca ;4
out (c),a ;12__64
rrca ;4
out (c),a ;12__16
ds 4 ;16
rrca ;4
out (c),a ;12__32
jp sloop ;10
Edit2: Example with modulation effect attached.
525 2017-05-30 20:47:47
Re: ZX Spectrum Next (25 replies, posted in Sinclair)
Yeah, I think SID is here to stay Port contention will be there in 48k mode, though it can probably be disabled with a setting.
I'm curious how good the beeper sound will be. I expect it to be at least on par with what garvalf recorded from his MiST.