Post by coltonhill01 on Apr 9, 2017 15:28:45 GMT
So, it's me again, a user of the software talking with the developer privately about accessibility issues. But I'll keep feature requests to this forum. Let's lay out what I think we should see.
1: anti aliasing waveforms.
As far as I can tell, the square and sawtooth waves, and probably the pulse too, are going to alias badly even on not so high notes. But the higher the note, the more aliasing will be introduced. You may not believe this, but consoles with PSG chips, never aliased once when it came to going over the niquist frequency. The only so called aliasing that occured on them was the bit level of some of the more complex curvish waveforms, such as triangles, sawtooths on wavetable chips that weren't the sid, and especially attempts at sine waves with the wavetable synths available, such as pc engine and nes expansions.
My suggestion is to put some sort of anti aliasing filter in place, if you don't want to band limit the square wave by harmonics then just band limit it with a lowpass filter at around 20000HZ before it makes it to the waveform output, that will kill aliasing and make your square wave sound pure and nice. Maybe even 15000HZ would be better for old beep style emulations.
2: more effects!
This is getting into the hard things to add, but if your syntax was inspired by mml, shouldn't you have some basic things that chiptunes pretty much always had? At least the fan compositions. Arps. At this moment, coding an arp would be painful as crap to the end user. But you can allow an arp macro to be generated, or some values defined or something. The arp should work as follows.
arptime=15 //ms
arp=0,4,7 //play the original note, then go up four semitones, then go up three because the deviation is from the root note. Then loop back to the tone.
playing C at this point would cause a major triad to be produced in arp format.
arp=0 //disables the effect.
3: make syntax a little bit easier on us?
One thing I absolutely hate about the syntax is that nearly everything is in uppercase. I'd constantly have to hold down my shift key as I typed commands to the engine. Things like notes, variables, and commands should not be case sensative. Keep them in uppercase to work with older tracks, but also allow them to be lowercase.
4: note lengths, and rests, oh my!
The length system is extremely flawed as I see it, compared to mml syntax. As mml defines it, the l command should set a default length, but this length can be overwritten by individual numbers placed directly after notes, with no whitespace. Also you can increase by the default length, but what if I wanted to add fractions of the length? Dots would be useful here, as well as some sort of tie form where I could say something like c~24 for a default length C plus a 24th note, or C. for length*=1.5. Make sure you interpret the number that may proceed the note first, before you do any dotting or tying. Rests would be nice as r, but I guess colon is okay.
5: revolutionize your synthesis technique!
This set of suggestions would by far be the hardest but best features to code into this thing, because they would give an entirely new sound to an otherwise plain little psg sounding blipbox.
5.1: sid, anyone?
The sid was probably the best chip of the 8bit sound era. Even though it was technically a 16 bit chip, it had that 8bit sound going on and so that's why I put it there. But it took it to a whole new level. One thing the sid could do was filter. Lowpass, highpass, bandpass or band reject, the sid could do some sick things like gigantic bases with nothing but a pulse wave and a filter. Now I am not saying to grab a sid emulator and steel it's filter code, just put some normal and smooth filters in the engine and give them type, band width for band filters, of course cutoff frequency, and reso level for that extra cool sid sound. Even better, allow the filter's params to be hooked up to an envelope of APDSR type as you've done with the volume, we could make some sick noise with that! Also the filter should be channel dependent, that is, work on it's own for every channel it is activated on.
5.2: more sid.
The sid was great. One thing everybody loved to do with the sid was play with it's pulse width in an LFO to create really cool sounds. Combined with the filter it made the sid's characteristic sound, other than the drums. So it would be nice to take your square wave and have a pw=, pwmrate=, and pwmdepth=, where pw is the pulse width in percent with decimal point percision up to I'd say 2 decimal places for things like 6.25 and 37.5, pwmrate= turns on the pwM LFO and sets it's rate in hertz, and pwmdepth= for the percent depth it should go in each direction from the original pw set earlier, or 50 if none. Maybe even add PWMLFO types, but I'd stick with a sine wave if I were you. Or you could hook it up to some new envelope command so I could make it fly out and stop.
5.3: the wave!
The greatest form of synthesis within the 8bit era, that is nes, was wavetable synthesis available on the expansion chips fds and namco163. These forms of wavetable synthesis took a sequence of numbers of a fixed length, or in case of namco, set of lengths, from 0 to a fixed upper boundary, and looped it at the frequency played by the note to create extremely cool sounds. Here's what I'm thinking for something of that sort, though it should be customizable.
@g //these will be defined globally.
WT0={length,ceiling,sample1 sample2 sample3 sample4 sample5 ... sample n...}
@1 //let's play one of those.
wavemode=wt //basic, wt or fm, (fm discussed later)
wt=0 //the instrument we would have defined.
cdefgab>c //a scale wavetable test.
etc...
I would set the maximum length of your wavetables to be 256 samples long, and probably do the wave lengths in multiples of 4 to avoid fucking over the loop. Also since wave I believe is floating point? You would scale the thing in half, call that the 0, and then do some math to get -1.0 to 1.0 ranges for all the wave samples, then just plop them at a wave thingage that you're using. Complex but great.
5.4: fm synthesis?
Fm synthesis is great, too. It was the sound of the 16 bit era other than sampling like the snes. This form of synthesis you should probably read up on, this post is getting lengthy anyways. Basically it takes one waveform, generally sine, and uses it to modulate the frequency of another waveform, also generally sine. These waveforms will have multipliers that are harmonically sound to produce nice harmonic sounds, or not to produce inharmonic bell like sounds and broken notes. It's kinda like your ringmod, and would probably be added in a similar way, by calling each channel an fm operator, either 2 or 4 operators in fm mode, pick the master one with probably op=1, the whole thing, or op=2/4 depending on what your op max is, and go from there. Fm needs some things to be fm. Frequency multipliers, or you could use notes and octaves if you wanna combine channels, ADSR, absolutely required per operator in fm, could use existing volume thingage, and waveform selection, either sine or half sine or whatever basic waveform you wanna use. Maybe even put wavetable in that, though that would probably sound like crap. Also fm allows one to link and unlink operators to form different patterns or algorithms, say op1 is hooked up to op2, the only algorithm for 2 op mode. OP1 is the carrier, op2 is the modulater. In 4 op mode, you can have different configs with hookups. 1>2/3>4, 1>2>3>4, 1/2>3/4, etc... And the volume of each operator effects it's intensity in the mix. Also feedback would make the operator feed back into it's own operation, producing harsher sounds. Probably do that one in percent. There are free fm models out there you should probably get for this sort of thing if you were to add it in.
5.5: wave drums?
By wave drums I mean using a wav file as a kick, snare, or hihat, which btw should have an open and a close. I could say something like kickwav=samples/kickdrum.wav to say hey, there's a kickdrum.wav file in this samples directory, relative to userdata I guess? That I wanna use. If I call kick, play it. Also make it so we can have a release mode, either stop when note ends or keep playing to make real drum kinda things.
That is the end of my extremely comprehensive post of feature requests and such, contact me if you need assistance with implementation, though be warned I know no c++. I'd like to see at least some of these features make it in, especially the ones before section 5. Section 5 is the big one with all the hard stuff in it. Also I'd like to see sid style features, but I don't necessarily need fm or wavetable synthesis.
Have a nice day, and may beep comp grow!
1: anti aliasing waveforms.
As far as I can tell, the square and sawtooth waves, and probably the pulse too, are going to alias badly even on not so high notes. But the higher the note, the more aliasing will be introduced. You may not believe this, but consoles with PSG chips, never aliased once when it came to going over the niquist frequency. The only so called aliasing that occured on them was the bit level of some of the more complex curvish waveforms, such as triangles, sawtooths on wavetable chips that weren't the sid, and especially attempts at sine waves with the wavetable synths available, such as pc engine and nes expansions.
My suggestion is to put some sort of anti aliasing filter in place, if you don't want to band limit the square wave by harmonics then just band limit it with a lowpass filter at around 20000HZ before it makes it to the waveform output, that will kill aliasing and make your square wave sound pure and nice. Maybe even 15000HZ would be better for old beep style emulations.
2: more effects!
This is getting into the hard things to add, but if your syntax was inspired by mml, shouldn't you have some basic things that chiptunes pretty much always had? At least the fan compositions. Arps. At this moment, coding an arp would be painful as crap to the end user. But you can allow an arp macro to be generated, or some values defined or something. The arp should work as follows.
arptime=15 //ms
arp=0,4,7 //play the original note, then go up four semitones, then go up three because the deviation is from the root note. Then loop back to the tone.
playing C at this point would cause a major triad to be produced in arp format.
arp=0 //disables the effect.
3: make syntax a little bit easier on us?
One thing I absolutely hate about the syntax is that nearly everything is in uppercase. I'd constantly have to hold down my shift key as I typed commands to the engine. Things like notes, variables, and commands should not be case sensative. Keep them in uppercase to work with older tracks, but also allow them to be lowercase.
4: note lengths, and rests, oh my!
The length system is extremely flawed as I see it, compared to mml syntax. As mml defines it, the l command should set a default length, but this length can be overwritten by individual numbers placed directly after notes, with no whitespace. Also you can increase by the default length, but what if I wanted to add fractions of the length? Dots would be useful here, as well as some sort of tie form where I could say something like c~24 for a default length C plus a 24th note, or C. for length*=1.5. Make sure you interpret the number that may proceed the note first, before you do any dotting or tying. Rests would be nice as r, but I guess colon is okay.
5: revolutionize your synthesis technique!
This set of suggestions would by far be the hardest but best features to code into this thing, because they would give an entirely new sound to an otherwise plain little psg sounding blipbox.
5.1: sid, anyone?
The sid was probably the best chip of the 8bit sound era. Even though it was technically a 16 bit chip, it had that 8bit sound going on and so that's why I put it there. But it took it to a whole new level. One thing the sid could do was filter. Lowpass, highpass, bandpass or band reject, the sid could do some sick things like gigantic bases with nothing but a pulse wave and a filter. Now I am not saying to grab a sid emulator and steel it's filter code, just put some normal and smooth filters in the engine and give them type, band width for band filters, of course cutoff frequency, and reso level for that extra cool sid sound. Even better, allow the filter's params to be hooked up to an envelope of APDSR type as you've done with the volume, we could make some sick noise with that! Also the filter should be channel dependent, that is, work on it's own for every channel it is activated on.
5.2: more sid.
The sid was great. One thing everybody loved to do with the sid was play with it's pulse width in an LFO to create really cool sounds. Combined with the filter it made the sid's characteristic sound, other than the drums. So it would be nice to take your square wave and have a pw=, pwmrate=, and pwmdepth=, where pw is the pulse width in percent with decimal point percision up to I'd say 2 decimal places for things like 6.25 and 37.5, pwmrate= turns on the pwM LFO and sets it's rate in hertz, and pwmdepth= for the percent depth it should go in each direction from the original pw set earlier, or 50 if none. Maybe even add PWMLFO types, but I'd stick with a sine wave if I were you. Or you could hook it up to some new envelope command so I could make it fly out and stop.
5.3: the wave!
The greatest form of synthesis within the 8bit era, that is nes, was wavetable synthesis available on the expansion chips fds and namco163. These forms of wavetable synthesis took a sequence of numbers of a fixed length, or in case of namco, set of lengths, from 0 to a fixed upper boundary, and looped it at the frequency played by the note to create extremely cool sounds. Here's what I'm thinking for something of that sort, though it should be customizable.
@g //these will be defined globally.
WT0={length,ceiling,sample1 sample2 sample3 sample4 sample5 ... sample n...}
@1 //let's play one of those.
wavemode=wt //basic, wt or fm, (fm discussed later)
wt=0 //the instrument we would have defined.
cdefgab>c //a scale wavetable test.
etc...
I would set the maximum length of your wavetables to be 256 samples long, and probably do the wave lengths in multiples of 4 to avoid fucking over the loop. Also since wave I believe is floating point? You would scale the thing in half, call that the 0, and then do some math to get -1.0 to 1.0 ranges for all the wave samples, then just plop them at a wave thingage that you're using. Complex but great.
5.4: fm synthesis?
Fm synthesis is great, too. It was the sound of the 16 bit era other than sampling like the snes. This form of synthesis you should probably read up on, this post is getting lengthy anyways. Basically it takes one waveform, generally sine, and uses it to modulate the frequency of another waveform, also generally sine. These waveforms will have multipliers that are harmonically sound to produce nice harmonic sounds, or not to produce inharmonic bell like sounds and broken notes. It's kinda like your ringmod, and would probably be added in a similar way, by calling each channel an fm operator, either 2 or 4 operators in fm mode, pick the master one with probably op=1, the whole thing, or op=2/4 depending on what your op max is, and go from there. Fm needs some things to be fm. Frequency multipliers, or you could use notes and octaves if you wanna combine channels, ADSR, absolutely required per operator in fm, could use existing volume thingage, and waveform selection, either sine or half sine or whatever basic waveform you wanna use. Maybe even put wavetable in that, though that would probably sound like crap. Also fm allows one to link and unlink operators to form different patterns or algorithms, say op1 is hooked up to op2, the only algorithm for 2 op mode. OP1 is the carrier, op2 is the modulater. In 4 op mode, you can have different configs with hookups. 1>2/3>4, 1>2>3>4, 1/2>3/4, etc... And the volume of each operator effects it's intensity in the mix. Also feedback would make the operator feed back into it's own operation, producing harsher sounds. Probably do that one in percent. There are free fm models out there you should probably get for this sort of thing if you were to add it in.
5.5: wave drums?
By wave drums I mean using a wav file as a kick, snare, or hihat, which btw should have an open and a close. I could say something like kickwav=samples/kickdrum.wav to say hey, there's a kickdrum.wav file in this samples directory, relative to userdata I guess? That I wanna use. If I call kick, play it. Also make it so we can have a release mode, either stop when note ends or keep playing to make real drum kinda things.
That is the end of my extremely comprehensive post of feature requests and such, contact me if you need assistance with implementation, though be warned I know no c++. I'd like to see at least some of these features make it in, especially the ones before section 5. Section 5 is the big one with all the hard stuff in it. Also I'd like to see sid style features, but I don't necessarily need fm or wavetable synthesis.
Have a nice day, and may beep comp grow!