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, ®) < 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