LoginSignup
11
11

More than 5 years have passed since last update.

音階が見えるビジュアライザー

Posted at

音階が見えるビジュアライザーです

Main.cpp
//はむくん ビジュアライザー 試作
# include <Siv3D.hpp>

class SoundPlayer
{
private:

    GUI m_gui;

    Sound m_sound;

    const Font m_font;

    const Vec2 m_centerPos;

    static const double m_freq[];

    static const bool m_isWhite[];

    static const String m_name[];

    bool m_isRecording;
public:

    SoundPlayer()
        : m_gui{ GUISkin::Default({ 0, 0, 0 }) }, m_font(10), m_centerPos(320, 190), m_isRecording(false)
    {
        m_gui.addButton(L"PlayButton", { L"Play" });

        m_gui.addButton(L"PauseButton", { L"Pause" });

        m_gui.addButton(L"OpenButton", { L"Open" });

        m_gui.addButton(L"UseMic", { L"Mic" });

        m_gui.addNewLine();

        m_gui.addSlider(L"Slider", { 0.0, 1.0, 0.0, 500 });

        m_gui.setPos((Window::Width() - m_gui.rect.w) / 2, 380);


    }

    void update()
    {
        m_gui.button(L"PlayButton").setEnabled(m_sound && !m_sound.isPlaying);

        m_gui.button(L"PauseButton").setEnabled(m_sound.isPlaying);

        m_gui.button(L"UseMic").setEnabled(!m_isRecording );

        m_gui.slider(L"Slider").setEnabled(!m_isRecording);

        if (m_gui.button(L"PlayButton").pushed)
        {
            m_sound.play();

            m_isRecording = false;

            Recorder::Stop();
        }
        else if (m_gui.button(L"PauseButton").pushed)
        {
            m_sound.pause();

            m_isRecording = false;

            Recorder::Stop();
        }
        else if (m_gui.button(L"OpenButton").pushed)
        {
            m_sound.pause();

            m_isRecording = false;

            Recorder::Stop();

            m_sound = Dialog::OpenSound();
        }

        if (m_gui.slider(L"Slider").hasChanged)
        {
            m_sound.setPosSec(m_sound.lengthSec*m_gui.slider(L"Slider").value);
        }

        m_gui.slider(L"Slider").setValue(m_sound.posSec / m_sound.lengthSec);

        if (m_gui.button(L"UseMic").pushed)
        {
            if (!Recorder::Start()){

            }
            else
            {
                m_isRecording = true;

                m_sound.pause();
            }
        }

    }

    void drawVisualizer() 
    {

        if (m_isRecording)
        {
            Waving::FFT(Recorder::GetWave(), Recorder::GetPos());
        }
        else
        {
            if (m_sound.isPlaying)Waving::FFT(m_sound);
        }


        const float* p = Waving::FFTBuffer();

        for (int i = 0; i < 12; ++i)
        {
            const double startRad = getRad((m_freq[i] + m_freq[i + 1]) / 2.0) + 0.01;

            const double angle = getRad((m_freq[i + 1] + m_freq[i + 2]) / 2.0) - startRad;

            const Vec2 pos = getPosFromRad( getRad(m_freq[i])) * (160.0) + m_centerPos;

            if (m_isWhite[i])
            { 
                Circle(m_centerPos, 180).drawPie(startRad, angle, Color(50));
            }
            else
            {
                Circle(m_centerPos, 180).drawPie(startRad, angle, Color(20));
            }

            m_font.drawCenter(m_name[i], pos,Color(70));
        }

        for (int i = 0; i<1760; ++i)
        {
            const double di = i;

            const double radian = getRad(di);

            const double radius = 0.0;

            const double radiusOuter = 180.0;

            const double width = Min(radiusOuter * ((radian)- getRad(di-1)), 50.0);

            const double size = Pow(p[i], 0.6f) * 800 * Log(di)/Log(10.0);

            const double strength = Pow(size , 2.0) * Log( di ) / 1000000.0;

            const Vec2 pos = getPosFromRad(radian) * (radius + size / 2.0) + m_centerPos;

            RectF(width, size).setCenter(pos).rotate(radian).draw(HSV(240 - Log( di ) * 100,1.0,strength));
        }



        if (m_isRecording && Recorder::IsEnd()) // 録音が終了
        {
            Recorder::Restart();
        }


    }

    double getRad(double freq) 
    {
        return 2 * Pi * Log(freq) / Log(2.0) + 2.42;
    }

    Vec2 getPosFromRad(double rad)
    {
        return Vec2(Sin(rad), -Cos(rad));
    }
};

const double SoundPlayer::m_freq[] = {
    440.000000,
    466.163762,
    493.883301,
    523.251131,
    554.365262,
    587.329536,
    622.253967,
    659.255114,
    698.456463,
    739.988845,
    783.990872,
    830.609395,
    880.000000,
    932.328
};

const bool SoundPlayer::m_isWhite[] = {
    false, true, true, false, true, false, true, false, true, true, false, true
};

const String SoundPlayer::m_name[] = {
    L"D", L"D#", L"E", L"F", L"F#", L"G", L"G#", L"A", L"A#", L"B", L"C", L"C#"
};

void Main()
{
    SoundPlayer soundPlayer;

    Graphics::Set2DBlendState(BlendState::Additive());

    while (System::Update())
    {
        soundPlayer.update();

        soundPlayer.drawVisualizer();       
    }
}
11
11
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
11