1 /***************************************************************************
2                           SidFilter.cpp  -  read filter
3                              -------------------
4     begin                : Sun Mar 11 2001
5     copyright            : (C) 2001 by Simon White
6     email                : s_a_white@email.com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #include <new>
19 #include <math.h>
20 #include <stdlib.h>
21 
22 #include "config.h"
23 #include "SidFilter.h"
24 
25 
SidFilter()26 SidFilter::SidFilter ()
27 :m_status(false)
28 {
29     m_errorString = "SID Filter: No filter loaded";
30 }
31 
~SidFilter()32 SidFilter::~SidFilter ()
33 {
34     clear ();
35 }
36 
clear()37 void SidFilter::clear ()
38 {
39     m_filter.points = 0;
40     m_status        = false;
41     m_errorString   = "SID Filter: No filter loaded";
42 }
43 
read(const char * filename)44 void SidFilter::read (const char *filename)
45 {
46     ini_fd_t ini = ini_open (filename, "r", ";");
47 
48     // Illegal ini fd
49     if (!ini)
50     {
51         m_status      = false;
52         m_errorString = "SID Filter: Unable to open filter file";
53         return;
54     }
55 
56     read (ini, "Filter");
57     ini_close (ini);
58 }
59 
read(ini_fd_t ini,const char * heading)60 void SidFilter::read (ini_fd_t ini, const char *heading)
61 {
62     int type = 1;
63 
64     clear ();
65     m_status = true;
66 
67     if (ini_locateHeading (ini, heading) < 0)
68     {
69         m_status = false;
70         m_errorString = "SID Filter: Unable to locate filter section in input file";
71         return;
72     }
73 
74     (void) ini_locateKey (ini, "type");
75     (void) ini_readInt   (ini, &type);
76     switch (type)
77     {
78     case 1:
79         readType1 (ini);
80     break;
81 
82     case 2:
83         readType2 (ini);
84     break;
85 
86     default:
87         m_status = false;
88         m_errorString = "SID Filter: Invalid filter type";
89     break;
90     }
91 }
92 
readType1(ini_fd_t ini)93 void SidFilter::readType1 (ini_fd_t ini)
94 {
95     int points;
96 
97     // Does Section exist in ini file
98     if (ini_locateKey (ini, "points") < 0)
99         goto SidFilter_readType1_errorDefinition;
100     if (ini_readInt (ini, &points) < 0)
101         goto SidFilter_readType1_errorDefinition;
102 
103     // Make sure there are enough filter points
104     if ((points < 2) || (points > 0x800))
105         goto SidFilter_readType1_errorDefinition;
106     m_filter.points = (uint_least16_t) points;
107 
108     // Set the ini reader up for array access
109     if (ini_listDelims (ini, ",") < 0)
110         goto SidFilter_readType1_errorMemory;
111 
112     {
113         char key[12];
114         int  reg = -1, fc = -1;
115         for (int i = 0; i < m_filter.points; i++)
116         {   // First lets read the SID cutoff register value
117             sprintf (key, "point%d", i + 1);
118             ini_locateKey (ini, key);
119             if (ini_readInt (ini, &reg) < 0)
120                 goto SidFilter_readType1_errorDefinition;
121             if (ini_readInt (ini, &fc)  < 0)
122                 goto SidFilter_readType1_errorDefinition;
123 
124             // Got valid reg/fc
125             m_filter.cutoff[i][0] = (uint) reg;
126             m_filter.cutoff[i][1] = (uint) fc;
127         }
128     }
129 return;
130 
131 SidFilter_readType1_errorDefinition:
132     clear ();
133     m_errorString = "SID Filter: Invalid Type 1 filter definition";
134     m_status = false;
135 return;
136 
137 SidFilter_readType1_errorMemory:
138     m_errorString = "SID Filter: Out of memory";
139     m_status = false;
140 }
141 
readType2(ini_fd_t ini)142 void SidFilter::readType2 (ini_fd_t ini)
143 {
144     double fs, fm, ft;
145 
146     // Read filter parameters
147     ini_locateKey (ini, "fs");
148     if (ini_readDouble (ini, &fs) < 0)
149         goto SidFilter_readType2_errorDefinition;
150     ini_locateKey (ini, "fm");
151     if (ini_readDouble (ini, &fm) < 0)
152         goto SidFilter_readType2_errorDefinition;
153     ini_locateKey (ini, "ft");
154     if (ini_readDouble (ini, &ft) < 0)
155         goto SidFilter_readType2_errorDefinition;
156 
157     // Calculate the filter
158     calcType2 (fs, fm, ft);
159 return;
160 
161 SidFilter_readType2_errorDefinition:
162     clear ();
163     m_errorString = "SID Filter: Invalid Type 2 filter definition";
164     m_status = false;
165 }
166 
167 // Calculate a Type 2 filter (Sidplay 1 Compatible)
calcType2(double fs,double fm,double ft)168 void SidFilter::calcType2 (double fs, double fm, double ft)
169 {
170     double fcMax = 1.0;
171     double fcMin = 0.01;
172     double fc;
173 
174     // Definition from reSID
175     m_filter.points = 0x100;
176 
177     // Create filter
178     for (uint i = 0; i < 0x100; i++)
179     {
180         uint rk = i << 3;
181         m_filter.cutoff[i][0] = rk;
182         fc = exp ((double) rk / 0x800 * log (fs)) / fm + ft;
183         if (fc < fcMin)
184             fc = fcMin;
185         if (fc > fcMax)
186             fc = fcMax;
187         m_filter.cutoff[i][1] = (uint) (fc * 4100);
188     }
189 }
190 
191 // Get filter
provide() const192 const sid_filter_t *SidFilter::provide () const
193 {
194     if (!m_status)
195         return NULL;
196     return &m_filter;
197 }
198 
199 // Copy filter from another SidFilter class
operator =(const SidFilter & filter)200 const SidFilter &SidFilter::operator= (const SidFilter &filter)
201 {
202     (void) operator= (filter.provide ());
203     return filter;
204 }
205 
206 // Copy sidplay2 sid_filter_t object
operator =(const sid_filter_t & filter)207 const sid_filter_t &SidFilter::operator= (const sid_filter_t &filter)
208 {
209     m_filter = filter;
210     m_status = true;
211     return filter;
212 }
213 
operator =(const sid_filter_t * filter)214 const sid_filter_t *SidFilter::operator= (const sid_filter_t *filter)
215 {
216     m_status = false;
217     if (filter)
218         (void) operator= (*filter);
219     return filter;
220 }
221