/* -*- mode: c; tab-width: 4; c-basic-offset: 4; c-file-style: "linux" -*- */ // // Copyright (c) 2009, Wei Mingzhi . // All rights reserved. // Created by Lou Yihua , 2015-08-03. // // This file is part of SDLPAL. // // SDLPAL is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // #include "dbemuopl.h" #include bool CDBemuopl::_inited = DBOPL::InitTables(); static inline int16_t conver_to_int16(int32_t sample) { if (sample > 32767) return 32767; else if (sample < -32768) return -32768; else return (int16_t)sample; } static inline uint8_t conver_to_uint8(int32_t sample) { if (sample > 32767) return 0xff; else if (sample < -32768) return 0; else return (uint8_t)(sample >> 8) ^ 0x80; } CDBemuopl::CDBemuopl(int rate, bool bit16, bool usestereo) : use16bit(bit16), stereo(usestereo), rate(rate) , maxlen(0), buffer(NULL) { currType = TYPE_OPL2; chip.Setup(rate); } CDBemuopl::~CDBemuopl() { if (buffer) delete[] buffer; } void CDBemuopl::init() { chip.Setup(rate); } void CDBemuopl::update(short *buf, int samples) { if (chip.opl3Active) update_opl3(buf, samples); else update_opl2(buf, samples); } void CDBemuopl::write(int reg, int val) { chip.WriteReg(reg, (Bit8u)val); } // OPL3 generate stereo samples void CDBemuopl::update_opl3(short *buf, int samples) { if (maxlen < samples * 2) { if (buffer) delete[] buffer; buffer = new int32_t[maxlen = samples * 2]; } chip.GenerateBlock3(samples, buffer); if (use16bit) { if (stereo) { for (int i = 0; i < samples * 2; i++) buf[i] = conver_to_int16(buffer[i]); } else { for (int i = 0; i < samples; i++) buf[i] = conver_to_int16((buffer[i * 2] + buffer[i * 2 + 1]) >> 1); } } else { uint8_t* outbuf = (uint8_t*)buf; if (stereo) { for (int i = 0; i < samples * 2; i++) outbuf[i] = conver_to_uint8(buffer[i]); } else { for (int i = 0; i < samples; i++) outbuf[i] = conver_to_uint8((buffer[i * 2] + buffer[i * 2 + 1]) >> 1); } } } // OPL2 generate mono samples void CDBemuopl::update_opl2(short *buf, int samples) { if (maxlen < samples) { if (buffer) delete[] buffer; buffer = new int32_t[maxlen = samples]; } chip.GenerateBlock2(samples, buffer); if (use16bit) { if (stereo) { for (int i = 0; i < samples; i++) buf[i * 2 + 1] = buf[i * 2] = conver_to_int16(buffer[i]); } else { for (int i = 0; i < samples; i++) buf[i] = conver_to_int16(buffer[i]); } } else { uint8_t* outbuf = (uint8_t*)buf; if (stereo) { for (int i = 0; i < samples; i++) outbuf[i * 2 + 1] = outbuf[i * 2] = conver_to_uint8(buffer[i]); } else { for (int i = 0; i < samples; i++) outbuf[i] = conver_to_uint8(buffer[i]); } } }