Mercurial > hg > aimc
comparison src/Modules/SSI/ModuleSSI.cc @ 15:b4cafba48e9d
-<math.h> replaced wit <cmath> where possible
-SSI support added but not yet tested
author | tomwalters |
---|---|
date | Fri, 19 Feb 2010 15:19:27 +0000 |
parents | 88fe02836a6b |
children | f4e712d41321 |
comparison
equal
deleted
inserted
replaced
14:ba2f7596d1a2 | 15:b4cafba48e9d |
---|---|
20 * \author Thomas Walters <tom@acousticscale.org> | 20 * \author Thomas Walters <tom@acousticscale.org> |
21 * \date created 2010/02/19 | 21 * \date created 2010/02/19 |
22 * \version \$Id$ | 22 * \version \$Id$ |
23 */ | 23 */ |
24 | 24 |
25 #include <cmath> | |
26 | |
25 #include "Modules/SSI/ModuleSSI.h" | 27 #include "Modules/SSI/ModuleSSI.h" |
26 | 28 |
27 namespace aimc { | 29 namespace aimc { |
28 ModuleSSI::ModuleSSI(Parameters *params) : Module(params) { | 30 ModuleSSI::ModuleSSI(Parameters *params) : Module(params) { |
29 module_description_ = "Size-shape image (aka the 'sscAI')"; | 31 module_description_ = "Size-shape image (aka the 'sscAI')"; |
30 module_identifier_ = "ssi"; | 32 module_identifier_ = "ssi"; |
31 module_type_ = "ssi"; | 33 module_type_ = "ssi"; |
32 module_version_ = "$Id$"; | 34 module_version_ = "$Id$"; |
33 | 35 |
34 do_pitch_cutoff_ = parameters_->DefaultBool("ssi.pitch_cutoff", false); | 36 //do_pitch_cutoff_ = parameters_->DefaultBool("ssi.pitch_cutoff", false); |
37 ssi_width_cycles_ = parameters_->DefaultFloat("ssi.width_cycles", 20.0f); | |
35 } | 38 } |
36 | 39 |
37 ModuleSSI::~ModuleSSI() { | 40 ModuleSSI::~ModuleSSI() { |
38 } | 41 } |
39 | 42 |
42 // that they can be checked later. | 45 // that they can be checked later. |
43 sample_rate_ = input.sample_rate(); | 46 sample_rate_ = input.sample_rate(); |
44 buffer_length_ = input.buffer_length(); | 47 buffer_length_ = input.buffer_length(); |
45 channel_count_ = input.channel_count(); | 48 channel_count_ = input.channel_count(); |
46 | 49 |
47 // If this module produces any output, then the output signal bank needs to | 50 float lowest_cf = input.centre_frequency(0); |
48 // be initialized here. | 51 ssi_width_samples_ = sample_rate_ * ssi_width_cycles_ / lowest_cf; |
49 // Example: | 52 if (ssi_width_samples_ > buffer_length_) { |
50 // output_.Initialize(channel_count, buffer_length, sample_rate); | 53 ssi_width_samples_ = buffer_length_; |
54 float cycles = ssi_width_samples_ * lowest_cf / sample_rate_; | |
55 LOG_INFO(_T("Requested SSI width of %f cycles is too long for the " | |
56 "input buffer length of %d samples. The SSI will be " | |
57 "truncated at %d samples wide. This corresponds to a width " | |
58 "of %f cycles."), ssi_width_cycles_, buffer_length_, | |
59 ssi_width_samples_, cycles); | |
60 ssi_width_cycles_ = cycles; | |
61 } | |
62 output_.Initialize(channel_count_, ssi_width_samples_, sample_rate_); | |
51 return true; | 63 return true; |
52 } | 64 } |
53 | 65 |
54 void ModuleSSI::ResetInternal() { | 66 void ModuleSSI::ResetInternal() { |
55 // Reset any internal state variables to their default values here. After a | |
56 // call to ResetInternal(), the module should be in the same state as it is | |
57 // just after a call to InitializeInternal(). | |
58 } | 67 } |
59 | 68 |
60 void ModuleSSI::Process(const SignalBank &input) { | 69 void ModuleSSI::Process(const SignalBank &input) { |
61 // Check to see if the module has been initialized. If not, processing | 70 // Check to see if the module has been initialized. If not, processing |
62 // should not continue. | 71 // should not continue. |
72 LOG_ERROR(_T("Mismatch between input to Initialize() and input to " | 81 LOG_ERROR(_T("Mismatch between input to Initialize() and input to " |
73 "Process() in module %s."), module_identifier_.c_str()); | 82 "Process() in module %s."), module_identifier_.c_str()); |
74 return; | 83 return; |
75 } | 84 } |
76 | 85 |
77 // Input is read from the input signal bank using calls like | 86 output_.set_start_time(input.start_time()); |
78 // float value = input_.sample(channel_number, sample_index); | |
79 | 87 |
80 // Output is fed into the output signal bank (assuming that it was | 88 for (int ch = 0; ch < channel_count_; ++ch) { |
81 // initialized during the call to InitializeInternal()) like this: | 89 // Copy the buffer from input to output, addressing by h-value |
82 // output_.set_sample(channel_number, sample_index, sample_value); | 90 for (int i = 0; i < ssi_width_samples_; ++i) { |
91 float h = static_cast<float>(i) * ssi_width_cycles_ | |
92 / static_cast<float>(ssi_width_samples_); | |
93 float cycle_samples = sample_rate_ / input.centre_frequency(ch); | |
83 | 94 |
95 // The index into the input array is a floating-point number, which is | |
96 // split into a whole part and a fractional part. The whole part and | |
97 // fractional part are found, and are used to linearly interpolate | |
98 // between input samples to yield an output sample. | |
99 double whole_part; | |
100 float frac_part = modf(h * cycle_samples, &whole_part); | |
101 int sample = static_cast<int>(whole_part); | |
102 | |
103 float val; | |
104 if (sample < buffer_length_ - 1) { | |
105 float curr_sample = input.sample(ch, sample); | |
106 float next_sample = input.sample(ch, sample + 1); | |
107 val = curr_sample + frac_part * (next_sample - curr_sample); | |
108 } else { | |
109 val = 0.0f; | |
110 } | |
111 output_.set_sample(ch, i, val); | |
112 } | |
113 } | |
84 PushOutput(); | 114 PushOutput(); |
85 } | 115 } |
86 } // namespace aimc | 116 } // namespace aimc |
87 | 117 |