C#利用NAudio制作用于音准训练的控制台应用

using System;
using System.Threading;
using System.Collections.Generic;
using NAudio.Wave;
using NAudio.Wave.SampleProviders;

namespace AudioTrain
{
    class Program
    {
        
        //根据ID生成音符名称
        private static string KeyName(int id)
        {
            List<string> abclist = new List<string>();
            abclist.AddRange(new string[] {"C", "Db", "D", "Eb", "E", "F", "Gb", "G", "Ab", "A", "Bb", "B"});
            int forenum = ((id - (id % 12)) / 12) - 1;
            string name = abclist[id % 12] + forenum.ToString();
            return name;
        }
        //根据ID获取音符频率
        //公式为:基准频率 * (2^1/12)^半音差 其中1/12约为0.08333...
        private static float KeyFrequency(int id)
        {
            int Basekey = 69;
            int BaseFrequency = 440;
            int semitone = id - Basekey;
            //Console.WriteLine(id);
            //Console.WriteLine(BaseFrequency * (float)Math.Pow((float)Math.Pow(2, 0.08333), semitone));
            float frequency = BaseFrequency * ((float)Math.Pow((float)Math.Pow(2, 0.08333), semitone));
            return frequency;
        }

        //static void AudioPlay()
        //{
        //
        //}
        //用于获取随机ID,可选择性输入参数用于修正随机数,防止与答案ID相同
        private static int RandomNum(int answer = 0, int isput = 0)
        {
            DateTime now = DateTime.Now;
            long tick = now.Ticks;
            //Console.WriteLine((int)tick);
            Random random = new Random((int)tick);
            int min = 57;
            int max = 81;
            int rand = random.Next(min, max+1);
            if (isput == 1 && rand == answer)
            {
                rand = rand + 1 + rand % 5;
            }
            return rand;
        }
        static void Main(string[] args)
        {
            Console.WriteLine("这是听音训练软件(控制台版)");
            Thread.Sleep(1000);
            Console.WriteLine("接下来顺着音阶播放声音...");
            using (WaveOut wave = new WaveOut())
            {
                //振荡器,用于产生基础波形的声音
                var signalGenerator = new SignalGenerator(44100, 2)
                {
                    Gain = 0.5, // 音量
                    Frequency = 440, // 音调频率(A4)
                    Type = SignalGeneratorType.Triangle // 三角波
                    //Type = SignalGeneratorType.Sin //正弦波
                    //Type = SignalGeneratorType.Square //方波
                };
                //统计次数和分数
                int score = 0;
                int times = 0;
                
                wave.Init(signalGenerator);
                
                for (int i = 57; i <= 81; i++)
                {
                    signalGenerator.Frequency = KeyFrequency(i);
                    wave.Play();
                    Thread.Sleep(400);
                    wave.Stop();
                    Thread.Sleep(100);

                }
                Console.WriteLine("接下来正式开始:");
                Thread.Sleep(2000);

                while (true)
                {
                    List<string> choicelist = new List<string>();
                    DateTime now = DateTime.Now;
                    long tick = now.Ticks;
                    Random random = new Random((int)tick);
                    int answernum = random.Next(0, 4);
                    int correctnum = RandomNum();
                    //Console.WriteLine(KeyName(correctnum));

                    //这里莫名奇妙加个休眠是
                    //因为DateTime.Now()转成int的精度似乎是不够
                    //直接运行下去会导致随机数种子相同
                    int id1 = RandomNum(correctnum, 1);
                    Thread.Sleep(80);
                    int id2 = RandomNum(correctnum, 1);
                    Thread.Sleep(80);
                    int id3 = RandomNum(correctnum, 1);
                    Thread.Sleep(80);
                    int id4 = RandomNum(correctnum, 1);

                    //以下全是简单粗暴的做法 (-_-)
                    if (id1 == id2 || id1 == id3 || id1 == id4) id1++;
                    else if (id2 == id3 || id2 == id4) id2++;
                    else if (id3 == id4) id3++;

                    switch (answernum){
                        case 0:
                            choicelist.Add(KeyName(correctnum));
                            choicelist.Add(KeyName(id2));
                            choicelist.Add(KeyName(id3));
                            choicelist.Add(KeyName(id4));
                            break;
                        case 1:
                            choicelist.Add(KeyName(id1));
                            choicelist.Add(KeyName(correctnum));
                            choicelist.Add(KeyName(id3));
                            choicelist.Add(KeyName(id4));
                            break;
                        case 2:
                            choicelist.Add(KeyName(id1));
                            choicelist.Add(KeyName(id2));
                            choicelist.Add(KeyName(correctnum));
                            choicelist.Add(KeyName(id4));
                            break;
                        case 3:
                            choicelist.Add(KeyName(id1));
                            choicelist.Add(KeyName(id2));
                            choicelist.Add(KeyName(id3));
                            choicelist.Add(KeyName(correctnum));
                            break;
                    }

                    Console.WriteLine("请根据所听到的声音进行选择:");
                    signalGenerator.Frequency = KeyFrequency( correctnum );

                    wave.Play();

                    Console.WriteLine("A:" + choicelist[0]);
                    Console.WriteLine("B:" + choicelist[1]);
                    Console.WriteLine("C:" + choicelist[2]);
                    Console.WriteLine("D:" + choicelist[3]);

                    // audioplay = new Thread(AudioPlay)
                    string getanswer = Console.ReadLine().ToLower();
                    bool isright = false;

                    switch (getanswer)
                    {
                        case "a":
                            if (answernum == 0) isright = true;
                            break;
                        case "b":
                            if (answernum == 1) isright = true;
                            break;
                        case "c":
                            if (answernum == 2) isright = true;
                            break;
                        case "d":
                            if (answernum == 3) isright = true;
                            break;
                    }
                    wave.Stop();

                    if (isright == true)
                    {
                        score++;
                        Console.WriteLine("回答正确");
                    }
                    else
                    {
                        Console.WriteLine("回答错误");
                        switch (answernum)
                        {
                            case 0:
                                Console.WriteLine("答案是:A");
                                break;
                            case 1:
                                Console.WriteLine("答案是:B");
                                break;
                            case 2:
                                Console.WriteLine("答案是:C");
                                break;
                            case 3:
                                Console.WriteLine("答案是:D");
                                break;
                        }
                        Thread.Sleep(2000);
                        Console.WriteLine("你的答案音调是:");
                        switch (getanswer)
                        {
                            case "a":
                                signalGenerator.Frequency = KeyFrequency(id1);
                                wave.Play();
                                Thread.Sleep(2000);
                                wave.Stop();
                                break;
                            case "b":
                                signalGenerator.Frequency = KeyFrequency(id2);
                                wave.Play();
                                Thread.Sleep(2000);
                                wave.Stop();
                                break;
                            case "c":
                                signalGenerator.Frequency = KeyFrequency(id3);
                                wave.Play();
                                Thread.Sleep(2000);
                                wave.Stop();
                                break;
                            case "d":
                                signalGenerator.Frequency = KeyFrequency(id4);
                                wave.Play();
                                Thread.Sleep(2000);
                                wave.Stop();
                                break;
                        }
                    }
                    times++;
                    Console.WriteLine("当前得分为:" + score);
                    Console.WriteLine("正确率为:" + String.Format("{0: 0.00}",((float)score/(float)times)*100) + "%");
                    Console.WriteLine("-----------------------");
                    Thread.Sleep(3000);
                    Console.Clear();
                }
            }
        }
    }
}

(做一个简单的分享,虽然说写的不咋地。。。)

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值