/** * Initiate the playing of a sound resource. * @param resnum Resource number */ void SoundGen2GS::play(int resnum) { AgiSoundEmuType type; _playingSound = resnum; type = (AgiSoundEmuType)_vm->_game.sounds[resnum]->type(); assert (type == AGI_SOUND_SAMPLE || type == AGI_SOUND_MIDI); if (_vm->_soundemu != SOUND_EMU_APPLE2GS) { warning("Trying to play sample or MIDI resource but not using Apple IIGS sound emulation mode"); return; } haltGenerators(); switch (type) { case AGI_SOUND_SAMPLE: { IIgsSample *sampleRes = (IIgsSample *) _vm->_game.sounds[_playingSound]; const IIgsSampleHeader &header = sampleRes->getHeader(); _channels[kSfxMidiChannel].setInstrument(&header.instrument); _channels[kSfxMidiChannel].setVolume(header.volume); midiNoteOn(kSfxMidiChannel, header.pitch, 127); break; } case AGI_SOUND_MIDI: ((IIgsMidi *) _vm->_game.sounds[_playingSound])->rewind(); _ticks = 0; break; default: break; } }
//***************************************************************************** // This example demonstrates MIDI functionality and control methods //***************************************************************************** int main(void){ // Set the clocking to run directly from the crystal. SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); // Enable the peripherals used by this VS1053. SysCtlPeripheralEnable(SYSCTL_PERIPH_UART1); // VS1053 Serial SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); // VS1053 Serial SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); // VS1053 Reset + EMG Input SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); // EMG Input 1 // Enable PC Console InitSerial(); // Enable processor interrupts. IntMasterEnable(); // Set GPIO B0 and B1 as UART pins for VS1053 Control GPIOPinConfigure(GPIO_PB0_U1RX); GPIOPinConfigure(GPIO_PB1_U1TX); GPIOPinTypeUART(GPIO_PORTB_BASE, GPIO_PIN_0 | GPIO_PIN_1); // Set GPIO E4 as Hardware Reset pin and E5 as ADC Input GPIOPinTypeGPIOOutput(GPIO_PORTE_BASE, GPIO_PIN_4); GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_5); // Configure the UART1 as according to VS1053 Datasheet with baudrate of 31250 UARTConfigSetExpClk(UART1_BASE, ROM_SysCtlClockGet(), 31250, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE)); // Setup ADC Sampling Sequences 3, configure step 0. // Note: Sequence 1 and 2 has 4 step, which would be great for 3-channel sampling ADCSequenceConfigure(ADC0_BASE, 3, ADC_TRIGGER_PROCESSOR, 0); ADCSequenceStepConfigure(ADC0_BASE, 3, 0, ADC_CTL_CH8 | ADC_CTL_IE | ADC_CTL_END); ADCSequenceEnable(ADC0_BASE, 3); ADCIntClear(ADC0_BASE, 3); // Example Started UARTprintf("VS1053 Test\n"); // Reset the VS1053 VS1053_Reset(); // Setup the MIDI Channel 0 midiSetChannelBank(0, VS1053_BANK_MELODY); midiSetInstrument(0, VS1053_GM1_OCARINA); midiSetChannelVolume(0, 127); midiNoteOn(0, 70, 127); Delay(1000); // Setup the MIDI Channel 1 midiSetChannelBank(1, VS1053_BANK_MELODY); midiSetInstrument(1, VS1053_GM1_OCARINA); midiSetChannelVolume(1, 0); midiNoteOn(1, 60, 127); // Setup variables for ADC uint32_t ADC_Output[1]; uint8_t volume; // Infinite Loop of execution while(1) { // ADC Sampling Procedures ADCProcessorTrigger(ADC0_BASE, 3); while(!ADCIntStatus(ADC0_BASE, 3, false)) {} ADCIntClear(ADC0_BASE, 3); ADCSequenceDataGet(ADC0_BASE, 3, ADC_Output); UARTprintf("AIN8 = %4d\n", ADC_Output[0]); // Play Sound as according to voltage level volume = inputMapping(ADC_Output[0], 3000, 4000, 50, 127); midiSetChannelVolume(0, volume); UARTprintf("Volume Level = %4d\n", volume); // Delay Delay(100); } }
void SoundGen2GS::playMidiSound() { if (_disabledMidi) return; const uint8 *p; uint8 parm1, parm2; static uint8 cmd, ch; if (_playingSound == -1 || _vm->_game.sounds[_playingSound] == NULL) { warning("Error playing Apple IIGS MIDI sound resource"); _playing = false; return; } IIgsMidi *midiObj = (IIgsMidi *) _vm->_game.sounds[_playingSound]; _playing = true; p = midiObj->getPtr(); midiObj->_soundBufTicks++; while (true) { uint8 readByte = *p; // Check for end of MIDI sequence marker (Can also be here before delta-time) if (readByte == MIDI_BYTE_STOP_SEQUENCE) { debugC(3, kDebugLevelSound, "End of MIDI sequence (Before reading delta-time)"); _playing = false; midiObj->rewind(); return; } else if (readByte == MIDI_BYTE_TIMER_SYNC) { debugC(3, kDebugLevelSound, "Timer sync"); p++; // Jump over the timer sync byte as it's not needed continue; } uint8 deltaTime = readByte; if (midiObj->_midiTicks + deltaTime > midiObj->_soundBufTicks) { break; } midiObj->_midiTicks += deltaTime; p++; // Jump over the delta-time byte as it was already taken care of // Check for end of MIDI sequence marker (This time it after reading delta-time) if (*p == MIDI_BYTE_STOP_SEQUENCE) { debugC(3, kDebugLevelSound, "End of MIDI sequence (After reading delta-time)"); _playing = false; midiObj->rewind(); return; } // Separate byte into command and channel if it's a command byte. // Otherwise use running status (i.e. previously set command and channel). if (*p & 0x80) { cmd = *p++; ch = cmd & 0x0f; cmd >>= 4; } switch (cmd) { case MIDI_CMD_NOTE_OFF: parm1 = *p++; parm2 = *p++; midiNoteOff(ch, parm1, parm2); break; case MIDI_CMD_NOTE_ON: parm1 = *p++; parm2 = *p++; midiNoteOn(ch, parm1, parm2); break; case MIDI_CMD_CONTROLLER: parm1 = *p++; parm2 = *p++; midiController(ch, parm1, parm2); break; case MIDI_CMD_PROGRAM_CHANGE: parm1 = *p++; midiProgramChange(ch, parm1); break; case MIDI_CMD_PITCH_WHEEL: parm1 = *p++; parm2 = *p++; uint16 wheelPos = ((parm2 & 0x7F) << 7) | (parm1 & 0x7F); // 14-bit value midiPitchWheel(wheelPos); break; } }
void SoundGen2GS::advanceMidiPlayer() { if (_disableMidi) return; const uint8 *p; uint8 parm1, parm2; static uint8 cmd, chn; if (_playingSound == -1 || _vm->_game.sounds[_playingSound] == NULL) { warning("Error playing Apple IIGS MIDI sound resource"); _playing = false; return; } IIgsMidi *midiObj = (IIgsMidi *) _vm->_game.sounds[_playingSound]; _ticks++; _playing = true; p = midiObj->getPtr(); while (true) { // Check for end of MIDI sequence marker (Can also be here before delta-time) if (*p == MIDI_STOP_SEQUENCE) { debugC(3, kDebugLevelSound, "End of MIDI sequence (Before reading delta-time)"); _playing = false; midiObj->rewind(); return; } if (*p == MIDI_TIMER_SYNC) { debugC(3, kDebugLevelSound, "Timer sync"); p++; // Jump over the timer sync byte as it's not needed continue; } // Check for delta time uint8 delta = *p; if (midiObj->_ticks + delta > _ticks) break; midiObj->_ticks += delta; p++; // Check for end of MIDI sequence marker (This time it after reading delta-time) if (*p == MIDI_STOP_SEQUENCE) { debugC(3, kDebugLevelSound, "End of MIDI sequence (After reading delta-time)"); _playing = false; midiObj->rewind(); return; } // Separate byte into command and channel if it's a command byte. // Otherwise use running status (i.e. previously set command and channel). if (*p & 0x80) { cmd = *p++; chn = cmd & 0x0f; cmd >>= 4; } switch (cmd) { case MIDI_NOTE_OFF: parm1 = *p++; parm2 = *p++; debugC(3, kDebugLevelSound, "channel %X: note off (key = %d, velocity = %d)", chn, parm1, parm2); midiNoteOff(chn, parm1, parm2); break; case MIDI_NOTE_ON: parm1 = *p++; parm2 = *p++; debugC(3, kDebugLevelSound, "channel %X: note on (key = %d, velocity = %d)", chn, parm1, parm2); midiNoteOn(chn, parm1, parm2); break; case MIDI_CONTROLLER: parm1 = *p++; parm2 = *p++; debugC(3, kDebugLevelSound, "channel %X: controller %02X = %02X", chn, parm1, parm2); // The tested Apple IIGS AGI MIDI resources only used // controllers 0 (Bank select?), 7 (Volume) and 64 (Sustain On/Off). // Controller 0's parameter was in range 94-127, // controller 7's parameter was in range 0-127 and // controller 64's parameter was always 0 (i.e. sustain off). switch (parm1) { case 7: _channels[chn].setVolume(parm2); break; } break; case MIDI_PROGRAM_CHANGE: parm1 = *p++; debugC(3, kDebugLevelSound, "channel %X: program change %02X", chn, parm1); _channels[chn].setInstrument(getInstrument(parm1)); break; case MIDI_PITCH_WHEEL: parm1 = *p++; parm2 = *p++; debugC(3, kDebugLevelSound, "channel %X: pitch wheel (unimplemented)", chn); break; default: debugC(3, kDebugLevelSound, "channel %X: unimplemented command %02X", chn, cmd); break; } }
void midiNoteOff(int note) { midiNoteOn(note, 0); }