Could you please fix so I could play the chord progression: "Gb7 Gmmaj7 Emmaj9 Ab9addb13/C Gbaug Bmaj9 Abm11 Dbm11 Gb7/#11 Dbmaj9sus2 Eb13sus4 Dbm9"
Also, as an example, 9b13 is the same as 9/b13 and 9addb13.
Add more capabilities to chord modifiers, keep the formatting the same (I don't like using redundant spaces between tokens, it's better to be concise and use ES6 tricks sometimes, but newlines and tab indentations are OK):
```js
var PI=Math.PI,TAU=PI*2,
    noteNumbers={
  "C":0,
  "C#":1,"Db":1,
  "D":2,
  "D#":3,"Eb":3,
  "E":4,
  "F":5,
  "F#":6,"Gb":6,
  "G":7,
  "G#":8,"Ab":8,
  "A":9,
  "A#":10,"Bb":10,
  "B":11
};
//parse a chord string into root note, modifiers, and bass note
function parseChordString(chordStr){
  /*
  //split the chord by slash to separate chord and bass note
  var parts=chordStr.split('/'),
      chordPart=parts[0],
      bassNote=parts[1]||null;
  */
  //check if the chord contains a bass note
  var bassNoteMatch=chordStr.match(/\/([A-G][#b]?)$/),
      bassNote=null;
  if(bassNoteMatch){
    bassNote=bassNoteMatch[1];
    chordStr=chordStr.slice(0,chordStr.length-bassNoteMatch[0].length); //remove bass note part from chordStr
  }
  //extract the root note and modifiers from the chordStr
  var match=chordStr.match(/^([A-G][#b]?)(.*)$/);
  if(!match)throw new Error("Invalid chord: "+chordStr);
  var rootNote=match[1],
      modifiers=match[2];
  return{
    rootNote:rootNote,
    modifiers:modifiers,
    bassNote:bassNote
  };
}
//function to parse chord modifiers into tokens
function parseModifiers(modifiers){
  // Patterns for different tokens
  var patterns=[
    {pattern:/^maj7/,token:'maj7'},
    {pattern:/^maj9/,token:'maj9'},
    {pattern:/^maj11/,token:'maj11'},
    {pattern:/^maj13/,token:'maj13'},
    {pattern:/^maj/,token:'maj'},
    {pattern:/^min13/,token:'min13'},
    {pattern:/^min11/,token:'min11'},
    {pattern:/^min9/,token:'min9'},
    {pattern:/^min7/,token:'min7'},
    {pattern:/^min/,token:'min'},
    {pattern:/^m/,token:'min'},
    {pattern:/^dim7/,token:'dim7'},
    {pattern:/^dim/,token:'dim'},
    {pattern:/^aug/,token:'aug'},
    {pattern:/^sus2/,token:'sus2'},
    {pattern:/^sus4/,token:'sus4'},
    {pattern:/^sus/,token:'sus'},
    {pattern:/^add\d+/,token:'add'},
    {pattern:/^6\/?9/,token:'6/9'},
    {pattern:/^7#9/,token:'7#9'},
    {pattern:/^7b9/,token:'7b9'},
    {pattern:/^7#5b9/,token:'7#5b9'},
    {pattern:/^7#5/,token:'7#5'},
    {pattern:/^7b5/,token:'7b5'},
    {pattern:/^7/,token:'7'},
    {pattern:/^5/,token:'5'},
    {pattern:/^6/,token:'6'},
    {pattern:/^9/,token:'9'},
    {pattern:/^11/,token:'11'},
    {pattern:/^13/,token:'13'},
    {pattern:/^#\d+/,token:'sharp'},
    {pattern:/^b\d+/,token:'flat'},
    {pattern:/^#/,token:'#'},
    {pattern:/^b/,token:'b'},
    {pattern:/^\//,token:'/'},
  ];
  var tokens=[],
      str=modifiers;
  while(str.length>0){
    var matched=false;
    for(var i=0;i<patterns.length;i++){
      var res=patterns[i].pattern.exec(str);
      if(res){
        if(patterns[i].token=='number'||patterns[i].token=='add'||patterns[i].token=='sharp'||patterns[i].token=='flat') {
          tokens.push(res[0]);
        }else{
          tokens.push(patterns[i].token);
        }
        str=str.substr(res[0].length);
        matched=true;
        break;
      }
    }
    if(!matched){
      //unrecognized token, skip one character
      str=str.substr(1);
    }
  }
  return tokens;
}
//function to get chord intervals based on modifiers
function getChordIntervals(modifiers){
  var tokens=parseModifiers(modifiers),
      intervals=[];
  //start with basic triad
  var chordQuality='major'; //default
  if(tokens.includes('maj')){
    chordQuality='major';
  }else if(tokens.includes('min')||tokens.includes('m')){
    chordQuality='minor';
  }else if(tokens.includes('dim')){
    chordQuality='diminished';
  }else if(tokens.includes('aug')){
    chordQuality='augmented';
  }
  //build the basic triad intervals
  if(chordQuality=='major'){
    intervals.push(0,4,7);
  }else if(chordQuality=='minor'){
    intervals.push(0,3,7);
  }else if(chordQuality=='diminished'){
    intervals.push(0,3,6);
  }else if(chordQuality=='augmented'){
    intervals.push(0,4,8);
  }
  //handle extensions and added tones
  if(tokens.includes('maj7')){
    intervals.push(11);
  }else if(tokens.includes('7')){
    intervals.push(10);
  }
  if(tokens.includes('9')){
    if(!intervals.includes(10)&&!intervals.includes(11))
      intervals.push(10); //add dominant 7th
    intervals.push(14);
  }
  if(tokens.includes('11')){
    if(!intervals.includes(10)&&!intervals.includes(11))
      intervals.push(10);
    if(!intervals.includes(14))intervals.push(14);
    intervals.push(17);
  }
  if(tokens.includes('13')){
    if(!intervals.includes(10)&&!intervals.includes(11))
      intervals.push(10);
    if(!intervals.includes(14))intervals.push(14);
    if(!intervals.includes(17))intervals.push(17);
    intervals.push(21);
  }
  if(tokens.includes('6/9'))
    intervals.push(9,14);
  if(tokens.includes('6'))
    intervals.push(9);
  if(tokens.includes('sus2')){
    //replace the third with major 2nd
    var index=intervals.indexOf(chordQuality=='major'?4:3);
    if(index>=0)intervals[index]=2;
  }else if(tokens.includes('sus4')){
    //replace the third with perfect 4th
    var index=intervals.indexOf(chordQuality=='major'?4:3);
    if(index>=0)intervals[index]=5;
  }
  //handle alterations
  for(var i=0;i<tokens.length;i++){
    if(tokens[i]=='#5'){
      //replace the fifth with augmented fifth
      var index=intervals.indexOf(7);
      if(index>=0)intervals[index]=8;
    }else if(tokens[i]=='b5'){
      //replace the fifth with diminished fifth
      var index=intervals.indexOf(7);
      if(index>=0)intervals[index]=6;
    }else if(tokens[i]=='#9'){
      intervals.push(15); //sharp ninth
    }else if(tokens[i]=='b9'){
      intervals.push(13); //flat ninth
    }else if(tokens[i]=='#11'){
      intervals.push(18); //sharp eleventh
    }else if(tokens[i]=='b13'){
      intervals.push(20); //flat thirteenth
    }
  }
  //remove duplicates and sort intervals
  intervals=intervals.filter((v,i,a)=>a.indexOf(v)===i);
  intervals.sort((a,b)=>a-b);
  return intervals;
}
function note(n,base=440,keys=12){return base*Math.pow(2,n/keys);}
function sine(x){return Math.sin(TAU*x);}
function pulse(x){return x%1<.5?-1:1;};
//limit frequency within a given range
function limitFrequency(freq,minFreq,maxFreq){
  while(freq<minFreq)freq*=2;
  while(freq>maxFreq)freq/=2;
  return freq;
}
var chordDuration=2, //seconds per chord
    chords="Amaj7sus2/Ab Gmaj7sus2 C69#11 Bm11 Ab7#5b9 Dbm11 Cmaj7b5/6 Abm11 F#m11".split(" "),
    totalChords = chords.length;
return function dsp(t) {
  var out=0,
      chordIndex=Math.floor(t/chordDuration)%totalChords,
      chordTime=t%chordDuration,
      chordStr=chords[chordIndex],
      chord=parseChordString(chordStr),
      rootNote=chord.rootNote,
      modifiers=chord.modifiers,
      bassNote=chord.bassNote||chord.rootNote,
      intervals=getChordIntervals(modifiers),
      rootNoteNumber=noteNumbers[rootNote],
      //get the semitone offset from A4 (note number 9)
      semitoneOffset=rootNoteNumber-9,
      //calculate frequencies and sum the sine waves
      numNotes=intervals.length+1; //number of notes in the chord including bass
  for(var i=0;i<intervals.length;i++){
    var n=semitoneOffset+intervals[i], //total semitone offset from A4
        freq=limitFrequency(note(n),220,880);
    out+=sine(freq*t);
  }
  //add the bass note an octave lower
  if(bassNote){
    var bassNoteNumber=noteNumbers[bassNote],
        bassSemitoneOffset=bassNoteNumber-9-12; //bass an octave lower
        bassFreq=note(bassSemitoneOffset);
    out+=sine(bassFreq*t);
  }
  //normalize output
  out=out/numNotes;
  return out;
}
```