Example

NX Music File API

5

SP4CEBAR 2022-07-19 16:28 (Edited)

Use this API if you want to make music software without having to worry about the NX Music File.

The number of subprograms in this library may seem overwhelming, but there is quite a bit of overlap between the commands

some subprograms match the NX subprogram commands
Like SOUND, ENVELOPE, LFO, LFO WAVE have a similar subprogram: W_SOUND, W_ENVELOPE, W_LFO, W_LFO_WAVE

If you like using NX's own sound commands then you can use them and copy the whole synthesizer data chunk into the file with the COPYSYNTH subprogram

You can use the read commands to display the current sound settings
You can use "SOUND SOURCE N" and "MUSIC" and MUSIC() to use and sync NX's built-in music player

Disclaimer: I haven't tested any of these subprograms, but I'm quite confident that most of it works

The NX music file can be divided up into the following sections, this library is based on those:

There are also subprograms in this library to save the file to the disk

A stands for address
W stands for write
R stands for read
WS stands for write single parameter
RS stands for read single parameter


'A L L   S U B P R O G R A M S   I N   T H I S   L I B R A R Y

'- PATTERNS   (NX MUSIC FILE): NUMBER (N) IS THE PATTERN NUMBER (0-63)
'  - A_PATTERN(N,O,A)        :  GET PATTERN ADDRESS(NUMBER,OFFSET,ADDRESS RETURN)
'  - WS_PATTERN(V,N,P)       :  WRITE SINGLE PATTERN(VOICE,NUMBER,PARAMETER)
'  - RS_PATTERN(V,N,P)       :  READ  SINGLE PATTERN(VOICE,NUMBER,PARAMETER RETURN)
'  - WS_FLAG(C,N,P)          :  WRITE SINGLE FLAG(FLAG,NUMBER,PARAMETER)
'  - RS_FLAG(C,N,P)          :  READ  SINGLE FLAG(FLAG,NUMBER,PARAMETER RETURN)
'  - W_FLAG(N,P0,P1,P2)      :  WRITE ALL    FLAGS(NUMBER,FLAG PARAMETERS...)
'  - R_FLAG(N,P0,P1,P2)      :  READ  ALL    FLAGS(NUMBER,FLAG PARAMETER RETURNS...)
'- PATTERN REDIRECTS         : PATTERN COMMANDS BUT SPECIFIED
'  - W_LOOPSTART(N,P)        :  WRITE THE LOOPSTART FLAG(PATTERN NUMBER,PARAMETER)
'  - R_LOOPSTART(N,P)        :  READ  THE LOOPSTART FLAG(PATTERN NUMBER,PARAMETER R)
'  - W_LOOPEND(N,P)          :  WRITE THE LOOPEND   FLAG(PATTERN NUMBER,PARAMETER)
'  - R_LOOPEND(N,P)          :  READ  THE LOOPEND   FLAG(PATTERN NUMBER,PARAMETER R)
'  - W_SONGSTOP(N,P)         :  WRITE THE SONGSTOP  FLAG(PATTERN NUMBER,PARAMETER)
'  - R_SONGSTOP(N,P)         :  READ  THE SONGSTOP  FLAG(PATTERN NUMBER,PARAMETER R)
'- TRACKS     (NX MUSIC FILE): TRACK NUMBER (N) (0-63) : TIME (T) (0-31)
'  - A_TRACK(N,T,O,A)        :  GET TRACK ADDRESS(NUMBER,TIME,OFFSET,ADDRESS RETURN)
'  - WS_TRACKBYTE(N,T,C,P)   :  WRITE SINGLE BYTE OF TRACK DATA(NUM,TIME,TYPE,PARAM)
'  - RS_TRACKBYTE(N,T,C,P)   :  READ  SINGLE BYTE OF TRACK DATA(NUM,TIME,TYPE,PARAM R)
'  - WS_NOTE(N,T,P)          :  WRITE SINGLE MUSIC NOTE        (NUM,TIME,PARAM)
'  - RS_NOTE(N,T,P)          :  READ  SINGLE MUSIC NOTE        (NUM,TIME,PARAM R)
'  - WS_TRACK(N,T,C,P)       :  WRITE SINGLE TRACK PARAMETER   (NUM,TIME,TYPE,PARAM)
'  - RS_TRACK(N,T,C,P)       :  READ  SINGLE TRACK PARAMETER   (NUM,TIME,TYPE,PARAM R)
'  - W_TRACK(N,T,P0,P1,P2,P3):  WRITE ALL    TRACK PARAMETERS  (NUM,TIME,PARAMS...)
'  - R_TRACK(N,T,P0,P1,P2,P3):  READ  ALL    TRACK PARAMETERS  (NUM,TIME,PARAMS R...)
'- TRACK REDIRECTS           : TRACK COMMANDS BUT SPECIFIED
'  - W_TRACKVOLUME(N,T,P)    :  WRITE VOLUME    (TRACK NUMBER,TIME,PARAMETER)
'  - R_TRACKVOLUME(N,T,P)    :  READ  VOLUME    (TRACK NUMBER,TIME,PARAMETER R)
'  - W_TRACKSYNTH(N,T,P)     :  WRITE SYNTH     (TRACK NUMBER,TIME,PARAMETER)
'  - R_TRACKSYNTH(N,T,P)     :  READ  SYNTH     (TRACK NUMBER,TIME,PARAMETER R)
'  - W_TRACKPARAMETER(N,T,P) :  WRITE PARAMETER (TRACK NUMBER,TIME,PARAMETER)
'  - R_TRACKPARAMETER(N,T,P) :  READ  PARAMETER (TRACK NUMBER,TIME,PARAMETER R)
'  - W_TRACKCOMMAND(N,T,P)   :  WRITE COMMAND   (TRACK NUMBER,TIME,PARAMETER)
'  - R_TRACKCOMMAND(N,T,P)   :  READ  COMMAND   (TRACK NUMBER,TIME,PARAMETER R)
'- SYNTHS     (NX MUSIC FILE): NUMBER (N) IS THE SYNTH NUMBER (0-15)
'  - A_SYNTH(N,O,A)          :  GET SYNTH ADDRESS(NUMBER,OFFSET,ADDRESS RETURN)
'  - W_SOUND(N,W,PW,LE)      :  WRITE ALL NX SOUND PARAMS(NUMBER,WAVE,PULSE WIDTH,LENGTH)
'  - R_SOUND(N,W,PW,LE,LEB)  :  READ  ALL NX SOUND PARAMS(NUMBER,WAVE,PULSE WIDTH,LENGTH)
'  - WS_SOUND(N,C,P)         :  WRITE SINGLE SOUND PARAMETER(NUMBER,TYPE,PARAMETER)
'  - RS_SOUND(N,C,P)         :  READ  SINGLE SOUND PARAMETER(NUMBER,TYPE,PARAMETER R)
'  - W_ENVELOPE(N,A,D,S,R)   :  WRITE ALL NX ENVELOPE PARS(NUM,ATTACK,DECAY,SUSTAIN,RELEASE)
'  - R_ENVELOPE(N,A,D,S,R)   :  READ  ALL NX ENVELOPE PARS(NUM,ATTACK,DECAY,SUSTAIN,RELEASE)
'  - WS_ENVELOPE(N,C,P)      :  WRITE SINGLE ENVELOPE PARAMETER(NUMBER,TYPE,PARAMETER)
'  - RS_ENVELOPE(N,C,P)      :  READ  SINGLE ENVELOPE PARAMETER(NUMBER,TYPE,PARAMETER R)
'  - W_LFO(N,R,FR,VOL,PW)    :  WRITE ALL NX LFO PARAMS(NUM,RATE,FREQ MOD,VOLUME MOD,PWM)
'  - R_LFO(N,R,FR,VOL,PW)    :  READ  ALL NX LFO PARAMS(NUM,RATE,FREQ MOD,VOLUME MOD,PWM)
'  - WS_LFO(N,C,P)           :  WRITE SINGLE LFO PARAMETER(NUMBER,TYPE,PARAMETER)
'  - RS_LFO(N,C,P)           :  READ  SINGLE LFO PARAMETER(NUMBER,TYPE,PARAMETER R)
'  - W_LFO_WAVE(N,W,I,E,T)   :  WRITE ALL NX LFO WAVE PARS(NUM,WAVE,INVERT,ENVELOPE,TRIGGER)
'  - R_LFO_WAVE(N,W,I,E,T)   :  READ  ALL NX LFO WAVE PARS(NUM,WAVE,INVERT,ENVELOPE,TRIGGER)
'  - WS_LFO_WAVE(N,C,P)      :  WRITE SINGLE LFO WAVE PARAMETER(NUMBER,TYPE,PARAMETER)
'  - RS_LFO_WAVE(N,C,P)      :  READ  SINGLE LFO WAVE PARAMETER(NUMBER,TYPE,PARAMETER R)
'- SYNTH REDIRECTS           : SYNTH COMMANDS BUT SPECIFIED
'  - VCO                     :
'    - W_PULSEWIDTH(N,P)     :  WRITE PULSE WIDTH   (SYNTH NUMBER,PARAMETER)
'    - R_PULSEWIDTH(N,P)     :  READ  PULSE WIDTH   (SYNTH NUMBER,PARAMETER R)
'    - W_VCOWAVE(N,P)        :  WRITE VCO WAVE TYPE (SYNTH NUMBER,PARAMETER)
'    - R_VCOWAVE(N,P)        :  READ  VCO WAVE TYPE (SYNTH NUMBER,PARAMETER R)
'    - W_LENGTH(N,P)         :  WRITE LENGTH        (SYNTH NUMBER,PARAMETER)
'    - R_LENGTH(N,P)         :  READ  LENGTH        (SYNTH NUMBER,PARAMETER R)
'  - ENVELOPE                :
'    - W_ATTACK(N,P)         :  WRITE ENVELOPE ATTACK  (SYNTH NUMBER,PARAMETER)
'    - R_ATTACK(N,P)         :  READ  ENVELOPE ATTACK  (SYNTH NUMBER,PARAMETER R) 
'    - W_DECAY(N,P)          :  WRITE ENVELOPE DECAY   (SYNTH NUMBER,PARAMETER) 
'    - R_DECAY(N,P)          :  READ  ENVELOPE DECAY   (SYNTH NUMBER,PARAMETER R)  
'    - W_SUSTAIN(N,P)        :  WRITE ENVELOPE SUSTAIN (SYNTH NUMBER,PARAMETER)  
'    - R_SUSTAIN(N,P)        :  READ  ENVELOPE SUSTAIN (SYNTH NUMBER,PARAMETER R)   
'    - W_RELEASE(N,P)        :  WRITE ENVELOPE RELEASE (SYNTH NUMBER,PARAMETER)   
'    - R_RELEASE(N,P)        :  READ  ENVELOPE RELEASE (SYNTH NUMBER,PARAMETER R) 
'  - LFO                     :
'    - W_LFORATE(N,P)        :  WRITE LFO RATE/SPEED             (SYNTH NUMBER,PARAMETER)
'    - R_LFORATE(N,P)        :  READ  LFO RATE/SPEED             (SYNTH NUMBER,PARAMETER R)
'    - W_FREQMOD(N,P)        :  WRITE LFO FREQUENCY   MODULATION (SYNTH NUMBER,PARAMETER)
'    - R_FREQMOD(N,P)        :  READ  LFO FREQUENCY   MODULATION (SYNTH NUMBER,PARAMETER R)
'    - W_VOLMOD(N,P)         :  WRITE LFO VOLUME      MODULATION (SYNTH NUMBER,PARAMETER)
'    - R_VOLMOD(N,P)         :  READ  LFO VOLUME      MODULATION (SYNTH NUMBER,PARAMETER R)
'    - W_PWMOD(N,P)          :  WRITE LFO PULSE WIDTH MODULATION (SYNTH NUMBER,PARAMETER)
'    - R_PWMOD(N,P)          :  READ  LFO PULSE WIDTH MODULATION (SYNTH NUMBER,PARAMETER R) 
'  - LFO WAVE                :
'    - W_LFOWAVE(N,P)        :  WRITE LFO WAVE TYPE    (SYNTH NUMBER,PARAMETER)
'    - R_LFOWAVE(N,P)        :  READ  LFO WAVE TYPE    (SYNTH NUMBER,PARAMETER R)
'    - W_LFOINV(N,P)         :  WRITE LFO INVERT   BIT (SYNTH NUMBER,PARAMETER) 
'    - R_LFOINV(N,P)         :  READ  LFO INVERT   BIT (SYNTH NUMBER,PARAMETER R) 
'    - W_LFOENV(N,P)         :  WRITE LFO ENVELOPE BIT (SYNTH NUMBER,PARAMETER) 
'    - R_LFOENV(N,P)         :  READ  LFO ENVELOPE BIT (SYNTH NUMBER,PARAMETER R) 
'    - W_LFOTRIG(N,P)        :  WRITE LFO TRIGGER  BIT (SYNTH NUMBER,PARAMETER) 
'    - R_LFOTRIG(N,P)        :  READ  LFO TRIGGER  BIT (SYNTH NUMBER,PARAMETER R) 
'- RAM                       :
'  - COPYSYNTH(V,N)          :  COPY A SYNTH FROM SOUND RAM TO THE FILE (TO USE NX COMMANDS)
'  - LOADSYNTH(V,N)          :  COPY A SYNTH FROM THE FILE TO SOUND RAM (TO PLAY IT)
'- DISK                      :
'  - SAVEMUSIC(F)            :  SAVE THE MUSIC FILE TO   ROM ENTRY "F" ON THE DISK
'  - LOADMUSIC(F)            :  LOAD THE MUSIC FILE FROM ROM ENTRY "F" ON THE DISK
'- BACKEND                   :
'  - WRITENIBBLE(A,C,P)      :  WRITE A 4-BIT PARAMETER(ADDRESS,LOW/HIGH,PARAMETER)
'  - READNIBBLE(A,C,P)       :  READ  A 4-BIT PARAMETER(ADDRESS,LOW/HIGH,PARAMETER R)
'  - WRITENIBBLES(A,P0,P1)   :  WRITE TWO 4-BIT PARAMETERS(ADDRESS,PARAMETERS...)
'  - READNIBBLES(A,P0,P1)    :  READ  TWO 4-BIT PARAMETERS(ADDRESS,PARAMETER RETURNS...)
'  - WRITEBITS(A,S,N,P)      :  WRITE AN N-BIT PARAMETER(ADDRESS,SIGNIFICANCE,LENGTH,PAR)
'  - READBITS(A,S,N,P)       :  READ  AN N-BIT PARAMETER(ADDRESS,SIGNIFICANCE,LENGTH,PAR R)
'  - WRITEBIT(A,S,P)         :  WRITE A 1-BIT PARAMETER(ADDRESS,SIGNIFICANCE,PARAMETER)
'  - READBIT(A,S,P)          :  READ  A 1-BIT PARAMETER(ADDRESS,SIGNIFICANCE,PARAMETER R)
'- Backend for the backend (new)
'  - READSEGMENT( VALUE, ADDRESS, DIVISOR, MODULO ) : reads a segment of bits
'  - RAMOVERLAY( ADDRESS, MASK, VALUE ) : overwrites a segment of bits

NX Music File API.nx | Open in app
2024-01-06 21:27
NX Music File API.nx | Open in app
2022-07-19 16:28

SP4CEBAR 2022-07-19 21:02 (Edited)

Making things structurized is fun, finally!


was8bit 2022-07-19 21:41

Wowzers!!!


SP4CEBAR 2022-07-20 07:52

My piano roll daw is a total mess, it has many arrays and variables, for all these parameters, and then it converts all that to the music file

But why convert if you can just work with the source, it's way simpler!


was8bit 2022-07-20 12:18

Yep, cool stuff :) i wish i had time to work on cool projects like these... lowres is so much fun :D


SP4CEBAR 2024-01-06 21:32 (Edited)

Update 1:

I noticed that I liked abbreviations when I made this. This means that you'll have to go to the API reference just to find what a variable does. I may remove these abbreviations at some point. However, I will not touch the API reference, as it is made so that it fits on one line on the NX app on my iPad.


SP4CEBAR 2024-01-07 16:50 (Edited)

Update 2


Log in to reply.