/** * PWM_SHIFT(): Shift PWM data. * @param src: Channel (L or R) with the source data. * @param dest Channel (L or R) for the destination. */ //#define PWM_SHIFT(src, dest) \ //{ \ // /* Make sure the source FIFO isn't empty. */ \ // if (PWM_RP_##src != PWM_WP_##src) \ // { \ // /* Get destination channel output from the source channel FIFO. */ \ // PWM_Out_##dest = PWM_FIFO_##src[PWM_RP_##src]; \ // \ // /* Increment the source channel read pointer, resetting to 0 if it overflows. */ \ // PWM_RP_##src = (PWM_RP_##src + 1) & (PWM_BUF_SIZE - 1); \ // } \ //} /*static void PWM_Shift_Data(void) * { * switch (PWM_Mode & 0x0F) * { * case 0x01: * case 0x0D: * // Rx_LL: Right -> Ignore, Left -> Left * PWM_SHIFT(L, L); * break; * * case 0x02: * case 0x0E: * // Rx_LR: Right -> Ignore, Left -> Right * PWM_SHIFT(L, R); * break; * * case 0x04: * case 0x07: * // RL_Lx: Right -> Left, Left -> Ignore * PWM_SHIFT(R, L); * break; * * case 0x05: * case 0x09: * // RR_LL: Right -> Right, Left -> Left * PWM_SHIFT(L, L); * PWM_SHIFT(R, R); * break; * * case 0x06: * case 0x0A: * // RL_LR: Right -> Left, Left -> Right * PWM_SHIFT(L, R); * PWM_SHIFT(R, L); * break; * * case 0x08: * case 0x0B: * // RR_Lx: Right -> Right, Left -> Ignore * PWM_SHIFT(R, R); * break; * * case 0x00: * case 0x03: * case 0x0C: * case 0x0F: * default: * // Rx_Lx: Right -> Ignore, Left -> Ignore * break; * } * } * * * void PWM_Update_Timer(unsigned int cycle) * { * // Don't do anything if PWM is disabled in the Sound menu. * * // Don't do anything if PWM isn't active. * if ((PWM_Mode & 0x0F) == 0x00) * return; * * if (PWM_Cycle == 0x00 || (PWM_Cycle_Cnt > cycle)) * return; * * PWM_Shift_Data(); * * PWM_Cycle_Cnt += PWM_Cycle; * * PWM_Int_Cnt--; * if (PWM_Int_Cnt == 0) * { * PWM_Int_Cnt = PWM_Int; * * if (PWM_Mode & 0x0080) * { * // RPT => generate DREQ1 as well as INT * SH2_DMA1_Request(&M_SH2, 1); * SH2_DMA1_Request(&S_SH2, 1); * } * * if (_32X_MINT & 1) * SH2_Interrupt(&M_SH2, 6); * if (_32X_SINT & 1) * SH2_Interrupt(&S_SH2, 6); * } * }*/ private int PWM_Update_Scale(pwm_chip chip, int PWM_In) { if (PWM_In == 0) { return(0); } // TODO: Chilly Willy's new scaling algorithm breaks drx's Sonic 1 32X (with PWM drums). //# ifdef CHILLY_WILLY_SCALE //return (((PWM_In & 0xFFF) - chip->PWM_Offset) * chip->PWM_Scale) >> (8 - PWM_Loudness); // Knuckles' Chaotix: Tachy Touch uses the values 0xF?? for negative values // This small modification fixes the terrible pops. PWM_In &= 0xFFF; if ((PWM_In & 0x800) != 0) { PWM_In |= ~0xFFF; } return(((PWM_In - chip.PWM_Offset) * chip.PWM_Scale) >> (8 - PWM_Loudness)); //#else // const int PWM_adjust = ((chip->PWM_Cycle >> 1) + 1); // int PWM_Ret = ((chip->PWM_In & 0xFFF) - PWM_adjust); // // Increase PWM volume so it's audible. // PWM_Ret <<= (5 + 2); // // Make sure the PWM isn't oversaturated. // if (PWM_Ret > 32767) // PWM_Ret = 32767; // else if (PWM_Ret < -32768) // PWM_Ret = -32768; // return PWM_Ret; //#endif }
private void PWM_Update(pwm_chip chip, int[][] buf, int length) { int tmpOutL; int tmpOutR; int i; //if (!PWM_Enable) // return; if (chip.PWM_Out_L == 0 && chip.PWM_Out_R == 0) { for (i = 0; i < length; i++) { buf[0][i] = 0; buf[1][i] = 0; } return; } // New PWM scaling algorithm provided by Chilly Willy on the Sonic Retro forums. tmpOutL = PWM_Update_Scale(chip, (int)chip.PWM_Out_L); tmpOutR = PWM_Update_Scale(chip, (int)chip.PWM_Out_R); for (i = 0; i < length; i++) { buf[0][i] = tmpOutL; buf[1][i] = tmpOutR; } }
public override void Update(byte ChipID, int[][] outputs, int samples) { pwm_chip chip = PWM_Chip[ChipID]; PWM_Update(chip, outputs, samples); visVolume[ChipID][0][0] = outputs[0][0]; visVolume[ChipID][0][1] = outputs[1][0]; }
//#endif private void PWM_Set_Cycle(pwm_chip chip, uint cycle) { cycle--; chip.PWM_Cycle = (cycle & 0xFFF); chip.PWM_Cycle_Cnt = chip.PWM_Cycles; //#if CHILLY_WILLY_SCALE // TODO: Fix Chilly Willy's new scaling algorithm. PWM_Recalc_Scale(chip); //#endif }
private void PWM_Set_Int(pwm_chip chip, uint int_time) { int_time &= 0x0F; if (int_time != 0) { chip.PWM_Int = chip.PWM_Int_Cnt = int_time; } else { chip.PWM_Int = chip.PWM_Int_Cnt = 16; } }
/** * PWM_Init(): Initialize the PWM audio emulator. */ private void PWM_Init(pwm_chip chip) { chip.PWM_Mode = 0; chip.PWM_Out_R = 0; chip.PWM_Out_L = 0; for (int i = 0; i < 8; i++) { chip.PWM_FIFO_R[i] = 0x00; chip.PWM_FIFO_L[i] = 0x00; } chip.PWM_RP_R = 0; chip.PWM_WP_R = 0; chip.PWM_RP_L = 0; chip.PWM_WP_L = 0; chip.PWM_Cycle_Tmp = 0; chip.PWM_Int_Tmp = 0; chip.PWM_FIFO_L_Tmp = 0; chip.PWM_FIFO_R_Tmp = 0; //PWM_Loudness = 0; PWM_Set_Cycle(chip, 0); PWM_Set_Int(chip, 0); }
private void pwm_chn_w(byte ChipID, byte Channel, uint data) { pwm_chip chip = PWM_Chip[ChipID]; if (chip.clock == 1) { // old-style commands switch (Channel) { case 0x00: chip.PWM_Out_L = data; break; case 0x01: chip.PWM_Out_R = data; break; case 0x02: PWM_Set_Cycle(chip, data); break; case 0x03: chip.PWM_Out_L = data; chip.PWM_Out_R = data; break; } } else { switch (Channel) { case 0x00 / 2: // control register PWM_Set_Int(chip, data >> 8); break; case 0x02 / 2: // cycle register PWM_Set_Cycle(chip, data); break; case 0x04 / 2: // l ch chip.PWM_Out_L = data; break; case 0x06 / 2: // r ch chip.PWM_Out_R = data; if (chip.PWM_Mode == 0) { if (chip.PWM_Out_L == chip.PWM_Out_R) { // fixes these terrible pops when // starting/stopping/pausing the song chip.PWM_Offset = (int)data; chip.PWM_Mode = 0x01; } } break; case 0x08 / 2: // mono ch chip.PWM_Out_L = data; chip.PWM_Out_R = data; if (chip.PWM_Mode == 0) { chip.PWM_Offset = (int)data; chip.PWM_Mode = 0x01; } break; } } return; }
public override void Reset(byte ChipID) { pwm_chip chip = PWM_Chip[ChipID]; PWM_Init(chip); }
private void PWM_Clear_Timer(pwm_chip chip) { chip.PWM_Cycle_Cnt = 0; }
//#if CHILLY_WILLY_SCALE // TODO: Fix Chilly Willy's new scaling algorithm. private void PWM_Recalc_Scale(pwm_chip chip) { chip.PWM_Offset = ((int)chip.PWM_Cycle / 2) + 1; chip.PWM_Scale = (0x7FFF00 / chip.PWM_Offset); }