/*************************************************************************** SidFilter.cpp - read filter ------------------- begin : Sun Mar 11 2001 copyright : (C) 2001 by Simon White email : s_a_white@email.com ***************************************************************************/ /*************************************************************************** * * * This program 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 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include #include #include #include "config.h" #include "SidFilter.h" SidFilter::SidFilter () :m_status(false) { m_errorString = "SID Filter: No filter loaded"; } SidFilter::~SidFilter () { clear (); } void SidFilter::clear () { m_filter.points = 0; m_status = false; m_errorString = "SID Filter: No filter loaded"; } void SidFilter::read (char *filename) { ini_fd_t ini = ini_open (filename, "r", ";"); // Illegal ini fd if (!ini) { m_status = false; m_errorString = "SID Filter: Unable to open filter file"; return; } read (ini, "Filter"); ini_close (ini); } void SidFilter::read (ini_fd_t ini, char *heading) { int type = 1; clear (); m_status = true; if (ini_locateHeading (ini, heading) < 0) { m_status = false; m_errorString = "SID Filter: Unable to locate filter section in input file"; return; } (void) ini_locateKey (ini, "type"); (void) ini_readInt (ini, &type); switch (type) { case 1: readType1 (ini); break; case 2: readType2 (ini); break; default: m_status = false; m_errorString = "SID Filter: Invalid filter type"; break; } } void SidFilter::readType1 (ini_fd_t ini) { int points; // Does Section exist in ini file if (ini_locateKey (ini, "points") < 0) goto SidFilter_readType1_errorDefinition; if (ini_readInt (ini, &points) < 0) goto SidFilter_readType1_errorDefinition; // Make sure there are enough filter points if ((points < 2) || (points > 0x800)) goto SidFilter_readType1_errorDefinition; m_filter.points = (uint_least16_t) points; // Set the ini reader up for array access if (ini_listDelims (ini, ",") < 0) goto SidFilter_readType1_errorMemory; { char key[12]; int reg = -1, fc = -1; for (int i = 0; i < m_filter.points; i++) { // First lets read the SID cutoff register value sprintf (key, "point%d", i + 1); ini_locateKey (ini, key); if (ini_readInt (ini, ®) < 0) goto SidFilter_readType1_errorDefinition; if (ini_readInt (ini, &fc) < 0) goto SidFilter_readType1_errorDefinition; // Got valid reg/fc m_filter.cutoff[i][0] = (uint) reg; m_filter.cutoff[i][1] = (uint) fc; } } return; SidFilter_readType1_errorDefinition: clear (); m_errorString = "SID Filter: Invalid Type 1 filter definition"; m_status = false; return; SidFilter_readType1_errorMemory: m_errorString = "SID Filter: Out of memory"; m_status = false; } void SidFilter::readType2 (ini_fd_t ini) { double fs, fm, ft; // Read filter parameters ini_locateKey (ini, "fs"); if (ini_readDouble (ini, &fs) < 0) goto SidFilter_readType2_errorDefinition; ini_locateKey (ini, "fm"); if (ini_readDouble (ini, &fm) < 0) goto SidFilter_readType2_errorDefinition; ini_locateKey (ini, "ft"); if (ini_readDouble (ini, &ft) < 0) goto SidFilter_readType2_errorDefinition; // Calculate the filter calcType2 (fs, fm, ft); return; SidFilter_readType2_errorDefinition: clear (); m_errorString = "SID Filter: Invalid Type 2 filter definition"; m_status = false; } // Calculate a Type 2 filter (Sidplay 1 Compatible) void SidFilter::calcType2 (double fs, double fm, double ft) { double fcMax = 1.0; double fcMin = 0.01; double fc; // Definition from reSID m_filter.points = 0x100; // Create filter for (uint i = 0; i < 0x100; i++) { uint rk = i << 3; m_filter.cutoff[i][0] = rk; fc = exp ((double) rk / 0x800 * log (fs)) / fm + ft; if (fc < fcMin) fc = fcMin; if (fc > fcMax) fc = fcMax; m_filter.cutoff[i][1] = (uint) (fc * 4100); } } // Get filter const sid_filter_t *SidFilter::provide () const { if (!m_status) return NULL; return &m_filter; } // Copy filter from another SidFilter class const SidFilter &SidFilter::operator= (const SidFilter &filter) { (void) operator= (filter.provide ()); return filter; } // Copy sidplay2 sid_filter_t object const sid_filter_t &SidFilter::operator= (const sid_filter_t &filter) { m_filter = filter; m_status = true; return filter; } const sid_filter_t *SidFilter::operator= (const sid_filter_t *filter) { m_status = false; if (filter) (void) operator= (*filter); return filter; }