- for(;ch<MAXCHAN;ch++) // loop em all... we will collect 1 ms of sound of each playing channel
- {
- if(s_chan[ch].bNew) StartSound(ch); // start new sound
- if(!s_chan[ch].bOn) continue; // channel not playing? next
-
- if(s_chan[ch].iActFreq!=s_chan[ch].iUsedFreq) // new psx frequency?
- VoiceChangeFrequency(ch);
-
- for(ns=ns_from;ns<ns_to;ns++) // loop until 1 ms of data is reached
- {
- if(s_chan[ch].bFMod==1 && iFMod[ns]) // fmod freq channel
- FModChangeFrequency(ch,ns);
-
- while(s_chan[ch].spos>=0x10000L)
- {
- if(s_chan[ch].iSBPos==28) // 28 reached?
- {
- start=s_chan[ch].pCurr; // set up the current pos
-
- if (start == (unsigned char*)-1) // special "stop" sign
- {
- s_chan[ch].bOn=0; // -> turn everything off
- s_chan[ch].ADSRX.lVolume=0;
- s_chan[ch].ADSRX.EnvelopeVol=0;
- goto ENDX; // -> and done for this channel
- }
-
- s_chan[ch].iSBPos=0;
-
- //////////////////////////////////////////// spu irq handler here? mmm... do it later
-
- s_1=s_chan[ch].s_1;
- s_2=s_chan[ch].s_2;
-
- predict_nr=(int)*start;start++;
- shift_factor=predict_nr&0xf;
- predict_nr >>= 4;
- flags=(int)*start;start++;
-
- // -------------------------------------- //
-
- for (nSample=0;nSample<28;start++)
- {
- d=(int)*start;
- s=((d&0xf)<<12);
- if(s&0x8000) s|=0xffff0000;
-
- fa=(s >> shift_factor);
- fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6);
- s_2=s_1;s_1=fa;
- s=((d & 0xf0) << 8);
-
- s_chan[ch].SB[nSample++]=fa;
-
- if(s&0x8000) s|=0xffff0000;
- fa=(s>>shift_factor);
- fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6);
- s_2=s_1;s_1=fa;
-
- s_chan[ch].SB[nSample++]=fa;
- }
-
- //////////////////////////////////////////// irq check
-
- if(irqCallback && (spuCtrl&0x40)) // some callback and irq active?
- {
- if((pSpuIrq > start-16 && // irq address reached?
- pSpuIrq <= start) ||
- ((flags&1) && // special: irq on looping addr, when stop/loop flag is set
- (pSpuIrq > s_chan[ch].pLoop-16 &&
- pSpuIrq <= s_chan[ch].pLoop)))
- {
- s_chan[ch].iIrqDone=1; // -> debug flag
- irqCallback(); // -> call main emu
-
- if(iSPUIRQWait) // -> option: wait after irq for main emu
- {
- iSpuAsyncWait=1;
- bIRQReturn=1;
- lastch=ch;
- lastns=ns;
- ns_to=ns+1;
- }
- }
- }
-
- //////////////////////////////////////////// flag handler
-
- if((flags&4) && (!s_chan[ch].bIgnoreLoop))
- s_chan[ch].pLoop=start-16; // loop adress
-
- if(flags&1) // 1: stop/loop
- {
- // We play this block out first...
- //if(!(flags&2)) // 1+2: do loop... otherwise: stop
- if(flags!=3 || s_chan[ch].pLoop==NULL) // PETE: if we don't check exactly for 3, loop hang ups will happen (DQ4, for example)
- { // and checking if pLoop is set avoids crashes, yeah
- start = (unsigned char*)-1;
- }
- else
- {
- start = s_chan[ch].pLoop;
- }
- }
-
- s_chan[ch].pCurr=start; // store values for next cycle
- s_chan[ch].s_1=s_1;
- s_chan[ch].s_2=s_2;
-
-GOON: ;
- }
-
- fa=s_chan[ch].SB[s_chan[ch].iSBPos++]; // get sample data
-
- StoreInterpolationVal(ch,fa); // store val for later interpolation
-
- s_chan[ch].spos -= 0x10000L;
- }
-
- if(s_chan[ch].bNoise)
- fa=iGetNoiseVal(ch); // get noise val
- else fa=iGetInterpolationVal(ch); // get sample val
-
- s_chan[ch].sval = (MixADSR(ch) * fa) / 1023; // mix adsr
-
- if(s_chan[ch].bFMod==2) // fmod freq channel
- iFMod[ns]=s_chan[ch].sval; // -> store 1T sample data, use that to do fmod on next channel
- else // no fmod freq channel
- {
- //////////////////////////////////////////////
- // ok, left/right sound volume (psx volume goes from 0 ... 0x3fff)
-
- if(s_chan[ch].iMute)
- s_chan[ch].sval=0; // debug mute
- else
- {
- SSumL[ns]+=(s_chan[ch].sval*s_chan[ch].iLeftVolume)/0x4000L;
- SSumR[ns]+=(s_chan[ch].sval*s_chan[ch].iRightVolume)/0x4000L;
- }
-
- //////////////////////////////////////////////
- // now let us store sound data for reverb
-
- if(s_chan[ch].bRVBActive) StoreREVERB(ch,ns);
- }
-
- ////////////////////////////////////////////////
- // ok, go on until 1 ms data of this channel is collected
-
- s_chan[ch].spos += s_chan[ch].sinc;
- }
-ENDX: ;
- }