00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef SPECTMORPH_IFFT_SYNTH_HH
00020 #define SPECTMORPH_IFFT_SYNTH_HH
00021
00022 #include <sys/types.h>
00023 #include <vector>
00024
00025 #include "smmath.hh"
00026
00027 namespace SpectMorph {
00028
00029 class IFFTSynthTable;
00030
00031 class IFFTSynth
00032 {
00033 IFFTSynthTable *table;
00034
00035 int zero_padding;
00036 size_t block_size;
00037 double mix_freq;
00038 double freq256_factor;
00039 double mag_norm;
00040
00041 float *fft_in;
00042 float *fft_out;
00043 float *win_scale;
00044
00045 enum {
00046 SIN_TABLE_SIZE = 4096,
00047 SIN_TABLE_MASK = 4095
00048 };
00049
00050 static std::vector<float> sin_table;
00051
00052 public:
00053 enum WindowType { WIN_BLACKMAN_HARRIS_92, WIN_HANNING };
00054 enum OutputMode { REPLACE, ADD };
00055
00056 IFFTSynth (size_t block_size, double mix_freq, WindowType win_type);
00057 ~IFFTSynth();
00058
00059 void
00060 clear_partials()
00061 {
00062 zero_float_block (block_size, fft_in);
00063 }
00064
00065 float*
00066 fft_buffer()
00067 {
00068 return fft_in;
00069 }
00070
00071 inline void render_partial (double freq, double mag, double phase);
00072 void get_samples (float *samples, OutputMode output_mode = REPLACE);
00073
00074 double quantized_freq (double freq);
00075 };
00076
00077 struct IFFTSynthTable
00078 {
00079 std::vector<float> win_trans;
00080
00081 float *win_scale;
00082 };
00083
00084 inline void
00085 IFFTSynth::render_partial (double mf_freq, double mag, double phase)
00086 {
00087 const int range = 4;
00088
00089 const int freq256 = sm_round_positive (mf_freq * freq256_factor);
00090 const int ibin = freq256 >> 8;
00091 float *sp = fft_in + 2 * (ibin - range);
00092 const float *wmag_p = &table->win_trans[(freq256 & 0xff) * (range * 2 + 1)];
00093
00094 const float nmag = mag * mag_norm;
00095
00096
00097
00098
00099 int iarg = sm_round_positive (phase * (SIN_TABLE_SIZE / (2 * M_PI)));
00100
00101
00102
00103 int iphase_adjust = freq256 * SIN_TABLE_SIZE / 512 + (SIN_TABLE_SIZE - SIN_TABLE_SIZE / 4);
00104 iarg += iphase_adjust;
00105
00106 const float phase_rsmag = sin_table [iarg & SIN_TABLE_MASK] * nmag;
00107 iarg += SIN_TABLE_SIZE / 4;
00108 const float phase_rcmag = sin_table [iarg & SIN_TABLE_MASK] * nmag;
00109
00110
00111 if (ibin > range && 2 * (ibin + range) < static_cast<int> (block_size))
00112 {
00113 for (int i = 0; i <= 2 * range; i++)
00114 {
00115 const float wmag = wmag_p[i];
00116 *sp++ += phase_rcmag * wmag;
00117 *sp++ += phase_rsmag * wmag;
00118 }
00119 }
00120 else
00121 {
00122 wmag_p += range;
00123 for (int i = -range; i <= range; i++)
00124 {
00125 const float wmag = wmag_p[i];
00126 if ((ibin + i) < 0)
00127 {
00128 fft_in[-(ibin + i) * 2] += phase_rcmag * wmag;
00129 fft_in[-(ibin + i) * 2 + 1] -= phase_rsmag * wmag;
00130 }
00131 else if ((ibin + i) == 0)
00132 {
00133 fft_in[0] += 2 * phase_rcmag * wmag;
00134 }
00135 else if (2 * (ibin + i) == static_cast<int> (block_size))
00136 {
00137 fft_in[1] += 2 * phase_rcmag * wmag;
00138 }
00139 else if (2 * (ibin + i) > static_cast<int> (block_size))
00140 {
00141 int p = block_size - (2 * (ibin + i) - block_size);
00142
00143 fft_in[p] += phase_rcmag * wmag;
00144 fft_in[p + 1] -= phase_rsmag * wmag;
00145 }
00146 else
00147 {
00148 fft_in[(ibin + i) * 2] += phase_rcmag * wmag;
00149 fft_in[(ibin + i) * 2 + 1] += phase_rsmag * wmag;
00150 }
00151 }
00152 }
00153 }
00154
00155 }
00156
00157 #endif