Music engine Muse 128b
evilpaul/Ate Bit
A muse is a thing that can outside─
come when you have a difficult task─
whose. Here the case was like this: I looked at 128-
gwEm's byte sound demonstrationson
Atari ST and decided - I should try it too─
go!
I have already written several musical plays─
yers for ZX at different times. Even when
Ate Bit did not officially exist, we will release─
rocked a couple of dem group evilpaul/CHMat/Eater
- and they just used my first ones
attempts in the field of creating players (I then─
where I didn’t even know it existed on the Spectrum─
trackers whine). Years passed and we switched to
a regular player from Vortex Tracker, but I
I’m still writing players for our little ones─
kih dem. The first one was for mipmap (2007
year) - there it was necessary to implement it in 1k
intro several effects and music to
surpass all old 1k intro. Of course
places to store real music
there was no data, so the notes were pulled out
straight from ROM. The main trick was in the under─
construction of data before playback, and most
simplethe way to do this is to interpret─
generate random data within a specific
scales. For example, like this:
0 -> C
1 -> D
2 -> E
3 -> F
4 -> G
5 -> A
6 -> B
7 -> C
8 -> Detc.
This way random data will end up in the tonal─
ness of C major, and it’s quite workable─
special way to get "satisfy─
really" sounding music from a random village─
research. All that is required is a table─
tsa pitches of notes in a major scale, which can─
can be easily generated from several
values. It turns out something like usual
tracker player, but we don’t know─
we place in the table of notes under the notes that
we don't use. You can even move
further and use 5 notes, so called─
my pentatonic scale. For example:
0 -> C
1 -> D
2 -> E
3 -> G
4 -> A
5 -> C
6 -> D
7 -> E
8 -> Getc.
The pentatonic scale is well known to guitarists -
everyone who tried to improvise melo─
diya or bass on the guitar, knows that if for─
press the pentatonic scale on the fretboard, then practically
everything you play sounds more than good─
xo. The same thing happens with transmission
data from ROM via pentatonic scale. If you
If you have implemented such a thing, then that’s enough─
strictly loop, for example, 16 bytes and search─
find good 16-byte sequences
in ROM. This could be quite a long pro─
cess, but in theory, if you loop something
several times, the brain itself will perceive it
like a melody. Remember this fact, we will not─
We'll be back again.
So now you can write a good one
melody for 1k demo, without storing notes at all─
ny text.Or can't you? There are two things
which you won’t get from random data─
nykh - instruments and drums. Tools
stored in the form of short tables with loud speakers─
tami and frequency shifts. Volume controls─
shape the sound envelope, and frequency shifts mo─
give vibrato or if necessary
other effects such as slides or legato.Li─
I usually write drums by hand. Four
pattern of four measures of four notes
each, rhythmically repeated in small increments─
The last change at the end takes 64 bytes.
This is too much for a 1k demo, but by the way─
Tew, it packs well.
I did a couple of 1k dems with this method and
also 1kdj, which uses the same sa─
mine, but with notes written by hand, not
taken from the ROM. In this case, a sacrifice was made─
be concerned with visual effects and graphics, but
there is a lot of space for a player and music
data. And one day at the beginning of 2014 I pi─
sal new small player for 4k demo.
This project evolved into the demo "Daytrip" (bu─
children shown at Sundown 2015) with great
music player that doesn't
will fit into 4k. But I had a few ideas
at the beginning of the development of this demo just
about a very tiny musical play─
yera. That's when I came across 128-bye─
Extensive sound demos from gwEm. After all
Obviously something similar can be done with
Spectrum?
The answer was, of course, “yes,” but for this
a couple more tricks were needed.Firstly,
in 128 bytes there is no room for any code, distortion─
giving random data, neither for the table
notes. But this is not a problem, since we already know─
I mean, what if you loop a random set of notes?
several times, the brain will decide that this is music.
It's easy to check: digitize for a couple of seconds
anything and scroll in a loop - at 9
In 10 cases it will pass for percussion.
Muse does just that. She plays alone
random set of notes, high, in quality
melody, and another set of notes, low and more
long, as a bass. Shocks are protected in
code in the form of a set of 4 notes. These 4 notes are
the first 4 bytes of the program, of which the first three
(SCF,NOP,NOP) do nothing, and the fourth
- this is the first real command in the program
(LD DE,nn). The drums are not a masterpiece, but they occupy
only three bytes.
Another new trick is that Muse
not synchronized with interrupts. Yes there─
noHALT. Instead she's just cool─
ticks in a short cycle between ticks and
finally updates the AY registers for an hour─
tote above 50 Hz - as a result, the sound is different─
only different from the players who play
at 50 Hz.
The player works with a 10-byte structure
data for each channel. To this structure
indicates registerIX - the player processes
one channel at a time. Mixer register in AY
is configured at the beginning of the program so that
one of the channels had noise turned on -
it will be drums.
Each channel has a timer, so...
nals play at different speeds - bass honey─
slower, drums faster. From the timer value
The current channel volume is also calculated.
The melodies are taken from ROM, but we indicate
only the HIGH byte of the address in the channel data─
la. With such a limitation it is quite difficult
find good patterns in the ROM, but again -
However, this saves a few bytes.
And finally, as you will see in the source,
Muse uses several bytes of data (by
three for each channel, plus one for kick─
nykh), which are outside the scope of prog─
frames. Calculated on what was there initially
there are zeros.
Here is the Muse source itself (compiled
pasmo assembler).
AYCTRL equ 65533
AYDATA equ 49149
org 32768
start
; the drum pattern is located at a circular address
;and takes 4 bytes
; we set three bytes, take the 4th
;from the command ld de,nn
; not the best drum option, but
;Only three bytes left...
drumPattern
db 0x37 ; scf
db 0 ; nop
db 0 ; nop
ld de,%110000+(7<<8);настраиваем
;регистр микшера
calloutAyByte
; -- главный цикл --
loop
ld ix,databass ; указатель на
;данные первого канала
call chanplay
db Oxdd,0x2e,LOW(datatune) ;ld lx
call chanplay
db Oxdd,0x2e,LOW(datadrums);ld lx
call chanplay
synca djnz synca
syncb add hl,sp ;хорошая, медленная,
;однобайтная инструкция...
djnz syncb
jr loop
; -- играть один канал --
chanplay
; обновляем таймер
ld a,(ix+CHA_TIMER)
sub (ix+CHA_SPEED)
ld (ix+CHA_TIMER),a
ld h,a ;запоминаем таймер для
;огибающей громкости ниже
jr nz,nonoteinc
; следующая нота
inc (ix+CHA_LOOPPOS)
ld a,(ix+CHA_LOOPPOS)
and (ix+CHA_REPEATLENGTHMASK)
jr nz,nonewpat
; следующий паттерн
ld a,(ix+CHA_PATTERNDATALOW)
add a,(ix+CHA_PATTERNDATASTEP)
ld (ix+CHA_PATTERNDATALOW),a
nonewpat
nonoteinc ld d,(ix+CHA_PATTERNDATAHIGH)
ld a,(ix+CHA_LOOPPOS)
and (ix+CHA_LOOPLENGTHMASK)
add a,(ix+CHA_PATTERNDATALOW)
ld e,a
ld a,(de)
ld d,(ix+CHAN_AYCOARSEPITCHCTRL)
ld e,a
call outAyByte;установим частоту
ld b,4
; h=таймер, >>4, чтобы получить громкость
vshift srl h
djnz vshift
ld d,(ix+CHAN_AYVOLCTRL)
ld e,h
; call outAyByte ;установим громкость
; ret
; d = ctrl, e = data
outAyByte
ldbc,AYCTRL
out (c),d
ld b,HIGH(AYDATA)
out (c),e
ret
CHAN_AYCOARSEPITCHCTRL equ 0
CHAN_AYVOLCTRL equ 1
CHA_PATTERNDATALOW equ 100
CHA_PATTERNDATAHIGH equ 2
CHA_TIMER equ 101
CHA_SPEED equ 3
CHA_LOOPPOS equ 102
CHA_LOOPLENGTHMASK equ 4
CHA_REPEATLENGTHMASK equ 5
CHA_PATTERNDATASTEP equ 6
databass
db 5
db 10
db 5
db 1
db %1
db %111
db 64
datatune
db 3
db 9
db 13
db 8
db %1111
db %111111
db 19
datadrums
db 1
db 8
db HIGH(drumPattern)
db 4
db %11
db %11
; db 0
end start
Share your thoughts about the article