マイク⇒ピッチ調節⇒スピーカー
KK 2016/03/15(Tue) 19:24
プログラミング初心者です。
マイク入力した音声のピッチを変えて、
スピーカーにリアルタイムで出力したいと思い、試行錯誤しています。
下記では、ピッチは変わるのですが、音がブツブツ切れます。
マイク入力のバッファ(秒数)を短くしても効果がなく、
短すぎると再生もされなくなります。
多少、入力⇒出力に遅れがあってもいいので、
きれいに再生ができる方法がありましたら、お願いします。
# include <Siv3D.hpp>
void Main()
{
Recorder recorder;
if (!recorder.open(0, 0.5s, RecordingFormat::S44100, false))
{
return;
}
if (!recorder.start())
{
return;
}
Sound sound(recorder.getWave());
sound.setLoop(false);
sound.play();
while (System::Update())
{
//★マイク入力が一杯になったら再生バッファに転送する。
if (recorder.isEnded())
{
sound.stop();
sound.fill(recorder.getWave());
sound.play();
recorder.start();
}
Line(315, 240, 325, 240).draw(4);//横軸
Line(320, 480, 320, 0).drawArrow(4, { 20, 20 });//縦軸
const Point pos = Mouse::Pos();
Circle(pos, 20).draw(Palette::Orange);
const double pitch = -(pos.y - 240) / 80.0;
sound.changePitchSemitones(pitch);
PutText(L"pitch: {} "_fmt, pitch).from(20, 20);
}
}
Reputeless 2016/03/16(Wed) 21:39
マイク入力の音声を直接 Sound に送るサンプルは次の通りです。
# include <Siv3D.hpp>
void Main()
{
const size_t BufferSize = 44100 * 10;
Recorder recorder(BufferSize);
recorder.start();
Sound sound(Wave(BufferSize), SoundLoop::All);
size_t readPos = 0;
size_t writePos = 0;
bool slow = false;
while (System::Update())
{
const size_t soundPos = sound.streamPosSample();
// ある程度変換後のサンプルがたまったら再生開始
if (!sound.isPlaying() && writePos > 8820)
{
sound.play();
}
if (soundPos < writePos)
{
const size_t diff = writePos - soundPos;
// この数字が小さいと、ずれは小さくなるがノイズが入りやすくなる
if (diff < 4410 && !slow)
{
// 再生が追い付いてきてバッファに余裕がなくなったら再生速度を少し落とす
sound.setSpeed(0.9);
slow = true;
}
else if(diff >=4410 && slow)
{
sound.setSpeed(1.0);
slow = false;
}
}
size_t readSize = recorder.getPosSample() - readPos;
while (readSize)
{
const size_t writeSize = Min(sound.lengthSample() - writePos, readSize);
sound.fill(writePos, &recorder.getWave()[readPos], writeSize);
writePos += writeSize;
if (writePos == BufferSize)
{
writePos = 0;
}
readPos += writeSize;
readSize -= writeSize;
}
if (recorder.isEnded())
{
readPos = 0;
recorder.start();
}
const double pitch = -(Mouse::Pos().y - 240) / 80.0;
sound.changePitchSemitones(pitch);
PutText(L"pitch: {}"_fmt, pitch).from(20, 20);
}
}