1 { 2 int i; 3 DATATYPE *buf = (DATATYPE *)buffer; 4 struct SN76496 *R = &sn[chip]; 5 6 7 /* If the volume is 0, increase the counter */ 8 for (i = 0;i < 4;i++) 9 { 10 if (R->Volume[i] == 0) 11 { 12 /* note that I do count += length, NOT count = length + 1. You might think */ 13 /* it's the same since the volume is 0, but doing the latter could cause */ 14 /* interferencies when the program is rapidly modulating the volume. */ 15 if (R->Count[i] <= length*STEP) R->Count[i] += length*STEP; 16 } 17 } 18 19 while (length > 0) 20 { 21 int vol[4]; 22 unsigned int out; 23 int left; 24 DATATYPE tmp; 25 26 /* vol[] keeps track of how long each square wave stays */ 27 /* in the 1 position during the sample period. */ 28 vol[0] = vol[1] = vol[2] = vol[3] = 0; 29 30 for (i = 0;i < 3;i++) 31 { 32 if (R->Output[i]) vol[i] += R->Count[i]; 33 R->Count[i] -= STEP; 34 /* Period[i] is the half period of the square wave. Here, in each */ 35 /* loop I add Period[i] twice, so that at the end of the loop the */ 36 /* square wave is in the same status (0 or 1) it was at the start. */ 37 /* vol[i] is also incremented by Period[i], since the wave has been 1 */ 38 /* exactly half of the time, regardless of the initial position. */ 39 /* If we exit the loop in the middle, Output[i] has to be inverted */ 40 /* and vol[i] incremented only if the exit status of the square */ 41 /* wave is 1. */ 42 while (R->Count[i] <= 0) 43 { 44 R->Count[i] += R->Period[i]; 45 if (R->Count[i] > 0) 46 { 47 R->Output[i] ^= 1; 48 if (R->Output[i]) vol[i] += R->Period[i]; 49 break; 50 } 51 R->Count[i] += R->Period[i]; 52 vol[i] += R->Period[i]; 53 } 54 if (R->Output[i]) vol[i] -= R->Count[i]; 55 } 56 57 left = STEP; 58 do 59 { 60 int nextevent; 61 62 63 if (R->Count[3] < left) nextevent = R->Count[3]; 64 else nextevent = left; 65 66 if (R->Output[3]) vol[3] += R->Count[3]; 67 R->Count[3] -= nextevent; 68 if (R->Count[3] <= 0) 69 { 70 if (R->RNG & 1) R->RNG ^= R->NoiseFB; 71 R->RNG >>= 1; 72 R->Output[3] = R->RNG & 1; 73 R->Count[3] += R->Period[3]; 74 if (R->Output[3]) vol[3] += R->Period[3]; 75 } 76 if (R->Output[3]) vol[3] -= R->Count[3]; 77 78 left -= nextevent; 79 } while (left > 0); 80 81 out = vol[0] * R->Volume[0] + vol[1] * R->Volume[1] + 82 vol[2] * R->Volume[2] + vol[3] * R->Volume[3]; 83 84 if (out > MAX_OUTPUT * STEP) out = MAX_OUTPUT * STEP; 85 86 tmp = ((DATACONV(out) * 3) >> 3); /* Dave: a bit quieter */ 87 88 /* Both channels */ 89 *(buf++) = tmp; 90 *(buf++) = tmp; 91 92 length--; 93 } 94 } 95