void CVRC7::EndFrame() { uint32_t WantSamples = m_pMixer->GetMixSampleCount(m_iTime); static int32_t LastSample = 0; // Generate VRC7 samples while (m_iBufferPtr < WantSamples) { int32_t RawSample = OPLL_calc(m_pOPLLInt.get()); // Clipping is slightly asymmetric if (RawSample > 3600) RawSample = 3600; if (RawSample < -3200) RawSample = -3200; // Apply volume int32_t Sample = int(float(RawSample) * m_fVolume); if (Sample > 32767) Sample = 32767; if (Sample < -32768) Sample = -32768; m_iBuffer[m_iBufferPtr++] = int16_t((Sample + LastSample) >> 1); LastSample = Sample; } m_pMixer->MixSamples((blip_sample_t*)m_iBuffer.data(), WantSamples); // // // m_iBufferPtr -= WantSamples; m_iTime = 0; }
// Update audio stream // This is periodically called by the sound engine void FM_Digital_WriteSamples(void *buffer, int length) { // Msg(MSGT_USER, "FM_Digital_WriteSamples(%p, %d)", buffer, length); // printf("\n[%s]\n", __FUNCTION__); s16* buf = (s16*)buffer; while (length--) { int val = OPLL_calc(opll) * 2; if (val < -0x8000) *buf = -0x8000; else if (val > 0x7FFF) *buf = 0x7FFF; else *buf = val; buf++; // printf("%d, ", buf[-1]); // printf("%d, ", val); } }
/* Run the virtual console emulation for one frame */ void sms_frame(int skip_render) { /* Take care of hard resets */ if(input.system & INPUT_HARD_RESET) { system_reset(); } /* Debounce pause key */ if(input.system & INPUT_PAUSE) { if(!sms.paused) { sms.paused = 1; z80_set_nmi_line(ASSERT_LINE); z80_set_nmi_line(CLEAR_LINE); } } else { sms.paused = 0; } if(snd.log) snd.callback(0x00); for(vdp.line = 0; vdp.line < 262; vdp.line += 1) { /* Handle VDP line events */ vdp_run(); /* Draw the current frame */ if(!skip_render) render_line(vdp.line); /* Run the Z80 for a line */ z80_execute(227); } /* Update the emulated sound stream */ if(snd.enabled) { int count; SN76496Update(0, snd.psg_buffer, snd.bufsize, sms.psg_mask); if(sms.use_fm) { int i; for(i = 0; i < snd.bufsize; i++) { snd.fm_buffer[i] = OPLL_calc(opll); } } for(count = 0; count < snd.bufsize; count += 1) { signed short left = 0; signed short right = 0; left = right = snd.fm_buffer[count]; left += snd.psg_buffer[0][count]; right += snd.psg_buffer[1][count]; snd.buffer[0][count] = left; snd.buffer[1][count] = right; } } }
int main(void){ static char wave[DATALENGTH*2] ; char filename[16] = "temp.wav" ; char header[46] ; int i; clock_t start,finish ; FILE *fp ; OPLL *opll ; /* Create WAVE header */ chunkID(header,"RIFF") ; DWORD(header+4,DATALENGTH*2+36) ; chunkID(header+8,"WAVE") ; chunkID(header+12,"fmt ") ; DWORD(header+16,16) ; WORD(header+20,1) ; /* WAVE_FORMAT_PCM */ WORD(header+22,1) ; /* channel 1=mono,2=stereo */ DWORD(header+24,SAMPLERATE) ; /* samplesPerSec */ DWORD(header+28,2*SAMPLERATE) ; /* bytesPerSec */ WORD(header+32,2) ; /* blockSize */ WORD(header+34,16) ; /* bitsPerSample */ chunkID(header+36,"data") ; DWORD(header+40,2*DATALENGTH) ; opll = OPLL_new(MSX_CLK,SAMPLERATE) ; OPLL_reset(opll); OPLL_writeReg(opll,0x30,0x30) ; /* select PIANO Voice to ch1. */ OPLL_writeReg(opll,0x10,0x80) ; /* set F-Number(L). */ OPLL_writeReg(opll,0x20,0x15) ; /* set BLK & F-Number(H) and keyon. */ start = clock() ; i=0; for(i=0;i<DATALENGTH;i++) { WORD(wave+i*2,OPLL_calc(opll)); } finish = clock() ; OPLL_delete(opll) ; printf("It has been %f sec to calc %d waves.\n", (double)(finish-start)/CLOCKS_PER_SEC, DATALENGTH) ; printf("%f times faster than real YM2413.\n", ((double)DATALENGTH/SAMPLERATE)/((double)(finish-start)/CLOCKS_PER_SEC)) ; fp = fopen(filename,"wb") ; if(fp == NULL) return 1 ; fwrite(header,46,1,fp) ; fwrite(wave,DATALENGTH,2,fp) ; fclose(fp) ; printf("Wrote : %s\n",filename) ; return 0 ; }