amplify
floatストリーム化でようやく振幅の調整をsine_waveから分離できました。
audio::pcm_format fmt; fmt.type = audio::pcm_format::int_le16; fmt.rate = 44100; fmt.channels = 1; io::copy( io::restrict( audio::amplify(audio::sine_wave_source(fmt.rate, 440.0), 0.5f), 0, calc_samples_per_note(fmt.rate, 100) ), audio::widen<float>(audio::pcm_sink(fmt)) );
float版sine_wave_sourceの要素はは-1.0〜1.0になるので、amplifyで0.5倍して-0.5〜0.5の範囲に抑えています。
1文字が1サンプルになるため、amplifyの実装は簡単です。
template<class Source> class amplifier { public: typedef typename boost::iostreams:: char_type_of<value_type>::type char_type; amplifier(const Source& src, float amp) : src_(src), amp_(amp) {} std::streamsize read(char_type* s, std::streamsize n) { std::streamsize amt = boost::iostreams::read(src_, s, n); if (amt != -1) { std::transform( s, s+amt, s, std::bind2nd( std::multiplies<char_type>(), static_cast<char_type>(amp_) ) ); } return amt; } // 他の関数は略 private: Source src_; // 増幅元のSource float amp_; // 増幅率 }; template<class Source> inline amplifier<Source> amplify(const Source& src, float amp) { return amplifier<Source>(src, amp); }
なお、上の実装ではワイド文字型が整数型の場合に増幅率が整数値になってしまい、よくありません。
実際には、文字型が整数型か浮動小数型かで場合分けをする必要があると思います。