zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

commit e88a3f74cf27a981c0127d422e1e9fef492f5e27
parent af0cd14c6307eb570e215173e9bda71ecf0d0204
Author: paulnasca <paulnasca>
Date:   Sat, 27 Mar 2004 18:08:59 +0000

*** empty log message ***

Diffstat:
Msrc/Makefile | 1+
Msrc/Misc/Master.C | 8++++----
Asrc/Seq/MIDIEvents.C | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/Seq/MIDIEvents.h | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/Seq/MIDIFile.C | 53++++++++++++++++++++++++++++++++++++++++++++---------
Msrc/Seq/MIDIFile.h | 17++++++++++++-----
Msrc/Seq/Makefile | 2+-
Msrc/Seq/Sequencer.C | 103+++++++++++++++++++++++++++++--------------------------------------------------
Msrc/Seq/Sequencer.h | 31+++----------------------------
9 files changed, 242 insertions(+), 112 deletions(-)

diff --git a/src/Makefile b/src/Makefile @@ -52,6 +52,7 @@ subdirs=DSP Effects Input Misc Output Params Synth Seq all: $(MAKE) -C UI $@ rm -f Make.deps + yes " " | head @for name in $(subdirs); do sh -c "cd $$name ; $(CXX) -MM -MG -w *.C >> ../Make.deps ; cd .."; done @for name in $(subdirs); do sh -c "make -C $$name $@"; done $(MAKE) objs diff --git a/src/Misc/Master.C b/src/Misc/Master.C @@ -220,10 +220,10 @@ void Master::AudioOut(REALTYPE *outl,REALTYPE *outr){ //test!!!!!!!!!!!!! se poate bloca aici (mutex) while (1){ - int type,par1,par2,again; - char chan=0;//deocamdata - again=seq.getevent(chan,&type,&par1,&par2); -// if (type!=0) printf("%d %d %d %d\n",type,chan,par1,par2); + int type,par1,par2,again,midichan; + char chan=1;//deocamdata + again=seq.getevent(chan,&midichan,&type,&par1,&par2); + if (type!=0) printf("%d %d %d %d %d\n",type,midichan,chan,par1,par2); if (again<=0) break; }; diff --git a/src/Seq/MIDIEvents.C b/src/Seq/MIDIEvents.C @@ -0,0 +1,73 @@ +/* + ZynAddSubFX - a software synthesizer + + MIDIEvents.C - It stores the midi events from midi file or sequencer + Copyright (C) 2003-2004 Nasca Octavian Paul + Author: Nasca Octavian Paul + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "MIDIEvents.h" +#include <stdlib.h> + +MIDIEvents::MIDIEvents(){ +}; + +MIDIEvents::~MIDIEvents(){ +}; + + +/************** Track stuff ***************/ +void MIDIEvents::writeevent(list *l,event *ev){ + listpos *tmp=new listpos; + tmp->next=NULL; + tmp->ev=*ev; + if (l->current!=NULL) l->current->next=tmp; + else l->first=tmp; + l->current=tmp; + l->size++; +}; + +void MIDIEvents::readevent(list *l,event *ev){ + if (l->current==NULL) { + ev->type=-1; + return; + }; + *ev=l->current->ev; + l->current=l->current->next; +}; + + +void MIDIEvents::rewindlist(list *l){ + l->current=l->first; +}; + +void MIDIEvents::deletelist(list *l){ + l->current=l->first; + if (l->current==NULL) return; + while (l->current->next!=NULL){ + listpos *tmp=l->current; + l->current=l->current->next; + delete(tmp); + }; + deletelistreference(l); +}; + +void MIDIEvents::deletelistreference(list *l){ + l->current=l->first=NULL; + l->size=0; + l->length=0.0; +}; diff --git a/src/Seq/MIDIEvents.h b/src/Seq/MIDIEvents.h @@ -0,0 +1,66 @@ +/* + ZynAddSubFX - a software synthesizer + + MIDIEvents.h - It stores the midi events from midi file or sequencer + Copyright (C) 2003-2004 Nasca Octavian Paul + Author: Nasca Octavian Paul + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ +#ifndef MIDI_EVENTS_H +#define MIDI_EVENTS_H + +#include "../globals.h" +#define NUM_MIDI_TRACKS NUM_MIDI_CHANNELS + +class MIDIEvents{ + friend class MIDIFile; + public: + MIDIEvents(); + ~MIDIEvents(); + + protected: + + /* Events */ + struct event{ + int deltatime; + int channel;//on what midi channel is + int type,par1,par2;//type=1 for note, type=2 for controller + } tmpevent; + struct listpos{ + event ev; + struct listpos *next; + }; + struct list{ + listpos *first,*current; + int size;//how many events are + double length;//in seconds + }; + struct { + list track;//the stored track + list record;//the track being "recorded" from midi + } miditrack[NUM_MIDI_TRACKS]; + + void writeevent(list *l,event *ev); + void readevent(list *l,event *ev); + + void rewindlist(list *l); + void deletelist(list *l); + void deletelistreference(list *l); + +}; + + +#endif diff --git a/src/Seq/MIDIFile.C b/src/Seq/MIDIFile.C @@ -30,6 +30,7 @@ MIDIFile::MIDIFile(){ midifilesize=0; midifilek=0; midieof=false; + me=NULL; }; MIDIFile::~MIDIFile(){ @@ -69,7 +70,8 @@ int MIDIFile::loadfile(char *filename){ return(0); }; -int MIDIFile::parsemidifile(){ +int MIDIFile::parsemidifile(MIDIEvents *me_){ + this->me=me_; //read the header int chunk=getint32();//MThd @@ -77,10 +79,11 @@ int MIDIFile::parsemidifile(){ int size=getint32(); if (size!=6) return(-1);//header is always 6 bytes long + int format=getint16(); printf("format %d\n",format); - int ntracks=getint16();//this is always if the format is "0" + int ntracks=getint16();//this is always 1 if the format is "0" printf("ntracks %d\n",ntracks); int division=getint16(); @@ -91,6 +94,8 @@ int MIDIFile::parsemidifile(){ printf("ERROR:in MIDIFile.C::parsemidifile() - SMPTE not implemented yet."); }; + if (ntracks>=NUM_MIDI_TRACKS) ntracks=NUM_MIDI_TRACKS-1; + for (int n=0;n<ntracks;n++){ if (parsetrack(n)<0) { clearmidifile(); @@ -102,6 +107,7 @@ int MIDIFile::parsemidifile(){ printf("\nMIDI file succesfully parsed.\n"); // printf("\n0x%x\n",getbyte()); + this->me=NULL; return(0); }; @@ -141,18 +147,18 @@ int MIDIFile::parsetrack(int ntrack){ switch(msg){ case 0x80 ... 0x8f://note on off - parsenoteon(msg & 0x0f,dt); + parsenoteon(ntrack,msg & 0x0f,dt); dt=0; break; case 0x90 ... 0x9f://note on (or note off) - parsenoteon(msg & 0x0f,dt); + parsenoteon(ntrack,msg & 0x0f,dt); dt=0; break; case 0xa0 ... 0xaf://aftertouch - ignored skipnbytes(2); break; case 0xb0 ... 0xbf://control change - parsecontrolchange(msg & 0x0f,dt); + parsecontrolchange(ntrack,msg & 0x0f,dt); dt=0; break; case 0xc0 ... 0xcf://program change - ignored @@ -201,26 +207,43 @@ int MIDIFile::parsetrack(int ntrack){ }; -void MIDIFile::parsenoteoff(char chan,unsigned int dt){ +void MIDIFile::parsenoteoff(char ntrack,char chan,unsigned int dt){ unsigned char note,vel; note=getbyte(); if (chan>=NUM_MIDI_CHANNELS) return; + me->tmpevent.deltatime=convertdt(dt); + me->tmpevent.type=1; + me->tmpevent.par1=note; + me->tmpevent.par2=0; + + + ///test + ntrack=0; + + me->writeevent(&me->miditrack[ntrack].record,&me->tmpevent); + printf("Note off:%d ",note); }; -void MIDIFile::parsenoteon(char chan,unsigned int dt){ +void MIDIFile::parsenoteon(char ntrack,char chan,unsigned int dt){ unsigned char note,vel; note=getbyte(); vel=getbyte(); if (chan>=NUM_MIDI_CHANNELS) return; + me->tmpevent.deltatime=convertdt(dt); + me->tmpevent.type=1; + me->tmpevent.par1=note; + me->tmpevent.par2=vel; + me->writeevent(&me->miditrack[ntrack].record,&me->tmpevent); + printf("[dt %d ] Note on:%d %d\n",dt,note,vel); }; -void MIDIFile::parsecontrolchange(char chan,unsigned int dt){ +void MIDIFile::parsecontrolchange(char ntrack,char chan,unsigned int dt){ unsigned char control,value; control=getbyte(); value=getbyte(); @@ -229,9 +252,15 @@ void MIDIFile::parsecontrolchange(char chan,unsigned int dt){ printf("[dt %d] Control change:%d %d\n",dt,control,value); + me->tmpevent.deltatime=convertdt(dt); + me->tmpevent.type=2; + me->tmpevent.par1=control;//???????????? ma uit la Sequencer::recordnote() din varianele vechi de zyn + me->tmpevent.par2=value; + me->writeevent(&me->miditrack[ntrack].record,&me->tmpevent); + }; -void MIDIFile::parsepitchwheel(char chan, unsigned int dt){ +void MIDIFile::parsepitchwheel(char ntrack,char chan, unsigned int dt){ unsigned char valhi,vallo; vallo=getbyte(); valhi=getbyte(); @@ -254,6 +283,12 @@ void MIDIFile::parsemetaevent(unsigned char mtype,unsigned char mlength){ }; +unsigned int MIDIFile::convertdt(unsigned int dt){ + double result=dt; + + return((int) (result*3.0)); +}; + void MIDIFile::clearmidifile(){ if (midifile!=NULL) delete(midifile); diff --git a/src/Seq/MIDIFile.h b/src/Seq/MIDIFile.h @@ -24,6 +24,7 @@ #define MIDIFILE_H #include "../globals.h" +#include "MIDIEvents.h" class MIDIFile{ public: @@ -34,9 +35,11 @@ class MIDIFile{ int loadfile(char *filename); //returns -1 if there is an error, otherwise 0 - int parsemidifile(); + int parsemidifile(MIDIEvents *me_); private: + MIDIEvents *me; + unsigned char *midifile; int midifilesize,midifilek; bool midieof; @@ -44,13 +47,16 @@ class MIDIFile{ //returns -1 if there is an error, otherwise 0 int parsetrack(int ntrack); - void parsenoteoff(char chan,unsigned int dt); - void parsenoteon(char chan,unsigned int dt); - void parsecontrolchange(char chan,unsigned int dt); - void parsepitchwheel(char chan, unsigned int dt); + void parsenoteoff(char ntrack,char chan,unsigned int dt); + void parsenoteon(char ntrack,char chan,unsigned int dt); + void parsecontrolchange(char ntrack,char chan,unsigned int dt); + void parsepitchwheel(char ntrack,char chan, unsigned int dt); void parsemetaevent(unsigned char mtype,unsigned char mlength); void clearmidifile(); + + //convert the delta-time to internal format + unsigned int convertdt(unsigned int dt); /* Low Level MIDIfile functions */ @@ -74,6 +80,7 @@ class MIDIFile{ struct { double tick;//how many seconds one tick has + }data; }; diff --git a/src/Seq/Makefile b/src/Seq/Makefile @@ -1,6 +1,6 @@ include ../Makefile.inc -objects=MIDIFile.o Sequencer.o +objects=MIDIEvents.o MIDIFile.o Sequencer.o all: $(objects) diff --git a/src/Seq/Sequencer.C b/src/Seq/Sequencer.C @@ -33,33 +33,44 @@ Sequencer::Sequencer(){ play=0; - for (int i=0;i<NUM_MIDI_CHANNELS;i++){ - midichan[i].track.first=NULL; - midichan[i].track.current=NULL; - midichan[i].track.size=0; - midichan[i].track.length=0.0; - midichan[i].record.first=NULL; - midichan[i].record.current=NULL; - midichan[i].record.size=0; - midichan[i].record.length=0.0; + for (int i=0;i<NUM_MIDI_TRACKS;i++){ + miditrack[i].track.first=NULL; + miditrack[i].track.current=NULL; + miditrack[i].track.size=0; + miditrack[i].track.length=0.0; + miditrack[i].record.first=NULL; + miditrack[i].record.current=NULL; + miditrack[i].record.size=0; + miditrack[i].record.length=0.0; }; resettime(&rectime); resettime(&playtime); - nextevent.time=-1.0;//must be less than 0 + nextevent.time=0.0;//must be less than 0 }; Sequencer::~Sequencer(){ - for (int i=0;i<NUM_MIDI_CHANNELS;i++){ - deletelist(&midichan[i].track); - deletelist(&midichan[i].record); + for (int i=0;i<NUM_MIDI_TRACKS;i++){ + deletelist(&miditrack[i].track); + deletelist(&miditrack[i].record); }; }; int Sequencer::importmidifile(char *filename){ if (midifile.loadfile(filename)<0) return(-1); - if (midifile.parsemidifile()<0) return(-1); + + for (int i=0;i<NUM_MIDI_TRACKS;i++){ + deletelist(&miditrack[i].record); + }; + if (midifile.parsemidifile(this)<0) return(-1); + + //copy the "record" track to the main track + for (int i=0;i<NUM_MIDI_TRACKS;i++){ + deletelist(&miditrack[i].track); + miditrack[i].track=miditrack[i].record; + deletelistreference(&miditrack[i].record); + }; return(0); }; @@ -71,7 +82,9 @@ void Sequencer::startplay(){ resettime(&playtime); //test - canalul 1, deocamdata - rewindlist(&midichan[0].track); + for (int i=0;i<NUM_MIDI_TRACKS;i++){ + rewindlist(&miditrack[i].track); + }; }; void Sequencer::stopplay(){ @@ -79,75 +92,35 @@ void Sequencer::stopplay(){ play=0; }; +// ************ Player stuff *************** -/************** Player stuff ***************/ - -int Sequencer::getevent(char chan,int *type,int *par1, int *par2){ +int Sequencer::getevent(char chan,int *midich, int *type,int *par1, int *par2){ *type=0; if (play==0) return(-1); updatecounter(&playtime); - if (nextevent.time>=playtime.abs) readevent(&midichan[chan].track,&nextevent.ev); +// printf("%g %g\n",nextevent.time,playtime.abs); + + if (nextevent.time<playtime.abs) readevent(&miditrack[chan].track,&nextevent.ev); else return(-1); if (nextevent.ev.type==-1) return(-1); +// printf("********************************\n"); + + *type=nextevent.ev.type; *par1=nextevent.ev.par1; *par2=nextevent.ev.par2; + *midich=nextevent.ev.channel; double dt=nextevent.ev.deltatime*0.001; nextevent.time+=dt; - printf("%f - %d %d \n",nextevent.time,par1,par2); +// printf("%f - %d %d \n",nextevent.time,par1,par2); return(0);//?? sau 1 }; - -/************** Track stuff ***************/ - - -void Sequencer::writeevent(list *l,event *ev){ - listpos *tmp=new listpos; - tmp->next=NULL; - tmp->ev=*ev; - if (l->current!=NULL) l->current->next=tmp; - else l->first=tmp; - l->current=tmp; - l->size++; -}; - -void Sequencer::readevent(list *l,event *ev){ - if (l->current==NULL) { - ev->type=-1; - return; - }; - *ev=l->current->ev; - l->current=l->current->next; -}; - - -void Sequencer::rewindlist(list *l){ - l->current=l->first; -}; - -void Sequencer::deletelist(list *l){ - l->current=l->first; - if (l->current==NULL) return; - while (l->current->next!=NULL){ - listpos *tmp=l->current; - l->current=l->current->next; - delete(tmp); - }; - deletelistreference(l); -}; - -void Sequencer::deletelistreference(list *l){ - l->current=l->first=NULL; - l->size=0; - l->length=0.0; -}; - /************** Timer stuff ***************/ void Sequencer::resettime(timestruct *t){ diff --git a/src/Seq/Sequencer.h b/src/Seq/Sequencer.h @@ -23,9 +23,10 @@ #define SEQUENCER_H #include "../globals.h" +#include "MIDIEvents.h" #include "MIDIFile.h" -class Sequencer{ +class Sequencer:public MIDIEvents{ public: Sequencer(); ~Sequencer(); @@ -38,7 +39,7 @@ class Sequencer{ //it returns 1 if this must be called at least once more //it returns 0 if there are no more notes for the current time //or -1 if there is no note - int getevent(char chan, int *type,int *par1, int *par2); + int getevent(char chan, int *midich,int *type,int *par1, int *par2); //returns 0 if ok or -1 if there is a error loading file int importmidifile(char *filename); @@ -53,32 +54,6 @@ class Sequencer{ MIDIFile midifile; - /* Events */ - struct event{ - int deltatime; - int type,par1,par2;//type=1 for note, type=2 for controller - } tmpevent; - struct listpos{ - event ev; - struct listpos *next; - }; - struct list{ - listpos *first,*current; - int size;//how many events are - double length;//in seconds - }; - struct { - list track//the stored track - ,record;//the track being recorded - } midichan[NUM_MIDI_CHANNELS]; - - void writeevent(list *l,event *ev); - void readevent(list *l,event *ev); - - void rewindlist(list *l); - void deletelist(list *l); - void deletelistreference(list *l); - /* Timer */ struct timestruct{ double abs;//the time from the begining of the track