/////////////////////////////////////////////////////////////////////////// // // SD_ShutAL() - Shuts down the AdLib card for sound effects // /////////////////////////////////////////////////////////////////////////// static void SD_ShutAL(void) { alSound = 0; YM3812Write(0, alEffects,0); YM3812Write(0, alFreqH + 0,0); SD_AlSetFXInst(&alZeroInst); }
/////////////////////////////////////////////////////////////////////////// // // SD_CleanAL() - Totally shuts down the AdLib card // /////////////////////////////////////////////////////////////////////////// static void SD_CleanAL(void) { int i; YM3812Write(0, alEffects,0); for (i = 1; i < 0xf5; i++) YM3812Write(0, i, 0); }
/////////////////////////////////////////////////////////////////////////// // // SD_DetectAdLib() - Determines if there's an AdLib (or SoundBlaster // emulating an AdLib) present // /////////////////////////////////////////////////////////////////////////// static boolean SD_DetectAdLib(void) { unsigned i; for (i = 1; i <= 0xf5; i++) /* Zero all the registers */ YM3812Write(0, i, 0); YM3812Write(0, 1, 0x20); /* Set WSE=1 */ return true; }
/////////////////////////////////////////////////////////////////////////// // // SD_Startup() - starts up the Sound Mgr // Detects all additional sound hardware and installs my ISR // /////////////////////////////////////////////////////////////////////////// void SD_Startup(void) { int i; if (SD_Started) return; if((audioMutex = SDL_CreateMutex()) == NULL) { printf("Unable to create audio mutex\n"); return; } if(Mix_OpenAudio(param_samplerate, AUDIO_S16, 2, param_audiobuffer)) { printf("Unable to open audio: %s\n", Mix_GetError()); return; } Mix_ReserveChannels(2); // reserve player and boss weapon channels Mix_GroupChannels(2, MIX_CHANNELS-1, 1); // group remaining channels // Init music if(YM3812Init(1,3579545,param_samplerate)) { printf("Unable to create virtual OPL!!\n"); } for(i=1; i<0xf6; i++) YM3812Write(oplChip,i,0,MAX_VOLUME); YM3812Write(oplChip,1,0x20,MAX_VOLUME); // Set WSE=1 // YM3812Write(0,8,0); // Set CSM=0 & SEL=0 // already set in for statement samplesPerMusicTick = param_samplerate / MUSIC_RATE; // SDL_t0FastAsmService played at 700Hz Mix_HookMusic(SDL_IMFMusicPlayer, 0); Mix_ChannelFinished(SD_ChannelFinished); AdLibPresent = true; SoundBlasterPresent = true; alTimeCount = 0; SD_SetSoundMode(sdm_Off); SD_SetMusicMode(smm_Off); SD_Started = true; SoundInfo.Init(); SoundSeq.Init(); }
// Drop-in replacement for id_sd.c:alOut void BE_ST_ALOut(uint8_t reg,uint8_t val) { BE_ST_LockAudioRecursively(); // RECURSIVE lock // FIXME: The original code for alOut adds 6 reads of the // register port after writing to it (3.3 microseconds), and // then 35 more reads of register port after writing to the // data port (23 microseconds). // // It is apparently important for a portion of the fuse // breakage sound at the least. For now a hack is implied. YM3812Write(&oplChip, reg, val); // Hack comes with a "magic number" // that appears to make it work better unsigned int length = OPL_SAMPLE_RATE / 10000; if (length > OPL_NUM_OF_SAMPLES - g_sdlALOutSamplesEnd) { BE_Cross_LogMessage(BE_LOG_MSG_WARNING, "BE_ST_ALOut overflow, want %u, have %u\n", length, OPL_NUM_OF_SAMPLES - g_sdlALOutSamplesEnd); // FIXME - Other thread length = OPL_NUM_OF_SAMPLES - g_sdlALOutSamplesEnd; } if (length) { YM3812UpdateOne(&oplChip, &g_sdlALOutSamples[g_sdlALOutSamplesEnd], length); g_sdlALOutSamplesEnd += length; } BE_ST_UnlockAudioRecursively(); // RECURSIVE unlock }
/////////////////////////////////////////////////////////////////////////// // // SD_MusicOff() - turns off the sequencer and any playing notes // returns the last music offset for music continue // /////////////////////////////////////////////////////////////////////////// int SD_MusicOff(void) { word i; sqActive = false; switch (MusicMode) { case SMM_ADLIB: YM3812Write(0, alEffects, 0); for (i = 0;i < sqMaxTracks;i++) YM3812Write(0, alFreqH + i + 1, 0); break; default: break; } return (int) (sqHackPtr-sqHack); }
/////////////////////////////////////////////////////////////////////////// // // SD_Startup() - starts up the Sound Mgr // Detects all additional sound hardware and installs my ISR // /////////////////////////////////////////////////////////////////////////// void SD_Startup(void) { int i; if (SD_Started) return; if(Mix_OpenAudio(44100, AUDIO_S16, 2, 2048)) return; /* Unable to open audio */ Mix_ReserveChannels(2); /* reserve player and boss weapon channels */ Mix_GroupChannels(2, MIX_CHANNELS-1, 1); /* group remaining channels */ /* Initialize music */ samplesPerMusicTick = 44100 / 700; /*played at 700Hzs */ if(YM3812Init(1, 3579545, 44100)) printf("Unable to create virtual OPL!!\n"); for(i=1;i<0xf6;i++) YM3812Write(0,i,0); YM3812Write(0,1,0x20); /* Set WSE=1 */ Mix_HookMusic(SD_IMFMusicPlayer, 0); Mix_ChannelFinished(SD_ChannelFinished); AdLibPresent = true; SoundBlasterPresent = true; alTimeCount = 0; SD_SetSoundMode(SDM_OFF); SD_SetMusicMode(SMM_OFF); SD_SetupDigi(); SD_Started = true; }
WLAudio::WLAudio(): m_adLib(false), m_soundBlaster(false), m_soundPositioned(0), m_numReadySamples(0), m_curAlSound(0), m_curAlSoundPtr(0), m_curAlLengthLeft(0), m_soundTimeCounter(5), m_originalSampleRate(7042), m_sqMaxTracks(10), m_alChar(0x20), m_alScale(0x40), m_alAttack(0x60), m_alSus(0x80), m_alWave(0xe0), m_alFreqL(0xa0), m_alFreqH(0xb0), m_alFeedCon(0xc0), m_alEffects(0xbd), m_nextSoundPos(false) { QAudioFormat format; #if QT_VERSION >= 0x050000 format.setSampleRate(param_samplerate); format.setChannelCount(2); #else format.setFrequency(param_samplerate); format.setChannels(2); #endif format.setByteOrder(QAudioFormat::LittleEndian); format.setCodec("audio/pcm"); format.setSampleSize(16); format.setSampleType(QAudioFormat::SignedInt); m_soundServer = new GameSoundServer(format); m_samplesPerMusicTick = param_samplerate / 700; if(YM3812Init(1,3579545,param_samplerate)) { printf("Unable to create virtual OPL!!\n"); } for(int i = 1;i < 0xf6;i++) YM3812Write(0,i,0); YM3812Write(0, 1, 0x20); // Set WSE=1 m_adLib = true; m_soundBlaster = true; m_alTimeCount = 0; setSoundMode(sdm_Off); setMusicMode(smm_Off); setupDigi(); }
void SD_ContinueMusic(int chunk, int startoffs) { SD_MusicOff(); if (MusicMode == SMM_ADLIB) { unsigned i; int32_t chunkLen = CA_CacheAudioChunk(chunk); sqHack = (word *)(void *) audiosegs[chunk]; /* alignment is correct */ if((word)Retro_SwapLES16(*sqHack) == 0) sqHackLen = sqHackSeqLen = chunkLen; else sqHackLen = sqHackSeqLen = (word)Retro_SwapLES16(*sqHack++); sqHackPtr = sqHack; if(startoffs >= sqHackLen) { Quit("SD_StartMusic: Illegal startoffs provided!"); } /* fast forward to correct position * (needed to reconstruct the instruments). */ for(i = 0; i < startoffs; i += 2) { byte reg = *(byte *)sqHackPtr; byte val = *(((byte *)sqHackPtr) + 1); if(reg >= 0xb1 && reg <= 0xb8) val &= 0xdf; /* disable play note flag */ else if(reg == 0xbd) val &= 0xe0; /* disable drum flags */ YM3812Write(0, reg,val); sqHackPtr += 2; sqHackLen -= 4; } sqHackTime = 0; alTimeCount = 0; SD_MusicOn(); } }
void CEmuopl::write(int reg, int val) { YM3812Write(0,0,reg); YM3812Write(0,1,val); }
void opl_write(int reg, int val) { YM3812Write(opl, 0, reg); YM3812Write(opl, 1, val); }
// Set the register at address 'addr' to the value 'data'. // Take care of data register to data register write delay. void SndOutput(int addr, int dataVal) { YM3812Write(ym3812p, 0, addr); YM3812Write(ym3812p, 1, dataVal); }
static void SD_IMFMusicPlayer(void *udata, Uint8 *stream, int len) { int stereolen = len>>1; int sampleslen = stereolen>>1; INT16 *stream16 = (INT16 *) (void *) stream; /* expect correct alignment */ while(1) { if(numreadysamples) { if(numreadysamples < sampleslen) { YM3812UpdateOne(0, stream16, numreadysamples); stream16 += numreadysamples*2; sampleslen -= numreadysamples; } else { YM3812UpdateOne(0, stream16, sampleslen); numreadysamples -= sampleslen; return; } } soundTimeCounter--; if(!soundTimeCounter) { soundTimeCounter = 5; if(curAlSound != alSound) { curAlSound = curAlSoundPtr = alSound; curAlLengthLeft = alLengthLeft; } if(curAlSound) { if(*curAlSoundPtr) { YM3812Write(0, alFreqL, *curAlSoundPtr); YM3812Write(0, alFreqH, alBlock); } else YM3812Write(0, alFreqH, 0); curAlSoundPtr++; curAlLengthLeft--; if(!curAlLengthLeft) { curAlSound = alSound = 0; SoundNumber = (soundnames) 0; SoundPriority = 0; YM3812Write(0, alFreqH, 0); } } } if(sqActive) { do { if(sqHackTime > alTimeCount) break; sqHackTime = alTimeCount + (word)Retro_SwapLES16(*(sqHackPtr+1)); YM3812Write(0, *(byte *) sqHackPtr, *(((byte *) sqHackPtr)+1)); sqHackPtr += 2; sqHackLen -= 4; } while(sqHackLen>0); alTimeCount++; if(!sqHackLen) { sqHackPtr = sqHack; sqHackLen = sqHackSeqLen; sqHackTime = 0; alTimeCount = 0; } } numreadysamples = samplesPerMusicTick; } }
/////////////////////////////////////////////////////////////////////////// // // SD_StartAL() - Starts up the AdLib card for sound effects // /////////////////////////////////////////////////////////////////////////// static void SD_StartAL(void) { YM3812Write(0, alEffects, 0); SD_AlSetFXInst(&alZeroInst); }
static void SD_AlSetFXInst(Instrument *inst) { byte m = 0; /* modulator cell for channel 0 */ byte c = 3; /* carrier cell for channel 0 */ YM3812Write(0, m + alChar,inst->mChar); YM3812Write(0, m + alScale,inst->mScale); YM3812Write(0, m + alAttack,inst->mAttack); YM3812Write(0, m + alSus,inst->mSus); YM3812Write(0, m + alWave,inst->mWave); YM3812Write(0, c + alChar,inst->cChar); YM3812Write(0, c + alScale,inst->cScale); YM3812Write(0, c + alAttack,inst->cAttack); YM3812Write(0, c + alSus,inst->cSus); YM3812Write(0, c + alWave,inst->cWave); YM3812Write(0, alFeedCon,0); }
/////////////////////////////////////////////////////////////////////////// // // SD_ALStopSound() - Turns off any sound effects playing through the // AdLib card // /////////////////////////////////////////////////////////////////////////// static void SD_ALStopSound(void) { alSound = 0; YM3812Write(0, alFreqH + 0, 0); }