首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在C#控制台应用程序中正确实现声音?

如何在C#控制台应用程序中正确实现声音?
EN

Stack Overflow用户
提问于 2018-01-17 22:38:17
回答 1查看 2.4K关注 0票数 3

我已经创建了一个控制台应用程序,它可以在控制台屏幕的任何地方创建文本。我想要创建一个类似效果的打字机,所以我从打字机中导入了一个击键声音,并在我的项目中使用了它。在屏幕上输入字符时,很难同步播放声音,所以我创建了一个名为声音的类,它为我想要在后台运行的每个声音创建一个背景线程。

现在我的字符与打字机的声音同步,我添加了一个新的声音文件。无论何时有新行,该文件都应播放。我现在面临的问题是,新的打字机车厢回音正在播放,突然停了下来。为了解决这个问题,我在PlaySync实例中添加了SoundPlayer ()命令。这允许我在后台播放新文件,但是当执行下一条消息时,回车声音仍然在播放,而字符正在被键入到控制台。回车结束后,击键声恢复正常。

我知道了发生这种情况的原因: PlaySync()将确保声音被加载和播放,然后恢复正常的操作。如果我使用的是PlaySync以外的任何东西,那么返回的车次将很快,甚至会被听到。我试过拖延一下,但还是不够完美。我想能够听到敲击的声音正在播放,一旦字符被键入。当执行新行时,我希望能够听到回车的声音。所有进程都必须在这个回车声音完成循环之后等待。同步这些声音的正确方法是什么?我的逻辑有缺陷吗?

Screen.cs

代码语言:javascript
运行
复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace CanizHospital
{
    public class Screen
    {
        private Sounds sounds;
        private const int delay = 300;
        private static int _leftPos;
        private static int _topPos;

        public Screen(int leftPos, int topPos, int screenWidth, int screenHeight)
        {
            _leftPos = leftPos;
            _topPos = topPos;
            sounds = new Sounds();
            SetUpScreen(screenWidth, screenHeight);
        }

        private static void SetUpScreen(int width, int height)
        {
            IntPtr ptr = GetConsoleWindow();
            MoveWindow(ptr, 0, 0, 1000, 400, true);
            Console.SetWindowSize(width, height);
        }

        public void WriteAt(string message, int x, int y, bool typeWritter)
        {
            try
            {
                Console.SetCursorPosition(_leftPos + x, _topPos + y);
                if(typeWritter && message != null)
                {
                    TypeWritter(message, delay);
                }
            }
            catch(ArgumentOutOfRangeException e)
            {
                Console.Clear();
                Console.Beep(37, 500);
                Console.Write(e.Message);
            }
        }

        public void TypeWritter(string message, int delay, bool newLine = true)
        {

            foreach (char c in message)
            {

                Console.Write(c);
                sounds.LoadTypewriterSound();
                Thread.Sleep(delay);
            }


            if(newLine)
            {    
                Console.Write(Environment.NewLine);
                sounds.LoadCarriageReturn();
                Thread.Sleep(delay);
            }    
        }

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr GetConsoleWindow();

        [DllImport("user32.dll", SetLastError = true)]
        internal static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
    }
}

Sounds.cs

代码语言:javascript
运行
复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Media;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace CanizHospital
{
    class Sounds
    {

        public void LoadTypewriterSound()
        {
            Thread backgroundSound = new Thread(new ThreadStart(PlayKey));
            backgroundSound.IsBackground = true;
            backgroundSound.Start();
        }

        public void LoadCarriageReturn()
        {
            Thread backgroundSound = new Thread(new ThreadStart(PlayCarriageReturn));
            backgroundSound.IsBackground = true;
            backgroundSound.Start();
        }

        private static void PlayKey()
        {
            SoundPlayer player = new SoundPlayer();
            player.SoundLocation = @"C:\Users\Erick\Desktop\C#\CanizHospital\CanizHospital\typewriter-key-1.wav";
            player.Play();
        }

        private static void PlayCarriageReturn()
        {
            SoundPlayer player = new SoundPlayer();
            player.SoundLocation = @"C:\Users\Erick\Desktop\C#\CanizHospital\CanizHospital\typewriter-return-1.wav";
            player.PlaySync();
        }
    }
}

代码语言:javascript
运行
复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Threading;
using Console = Colorful.Console;
using Colorful;

namespace CanizHospital
{
    class Program
    {

        static void Main(string[] args)
        {
            Screen screen = new Screen(Console.CursorLeft, Console.CursorTop, 
                Console.LargestWindowWidth, Console.LargestWindowHeight);


            screen.WriteAt("Hi whats up", 0, 0, true);
            //Thread.sleep(500);  //Delay here wont stop process
            screen.WriteAt("Hi whats up", 1, 1, true);
        }
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-01-18 00:10:18

首先,您不需要创建一个新线程来保存一个SoundPlayer实例来调用Play()。您可以在Play()之前调用Console.Write,在延迟之后调用Stop() (或者您无法听到任何消息,因为它停止得太快)。从MSDN,Play()方法

使用.wav新线程播放文件,如果未加载.wav文件,则先加载.wav文件。

其次,PlaySync()在完成之前阻止执行,这完全符合您的要求:

PlaySync方法使用当前线程来播放.wav文件,防止线程在加载完成之前处理其他消息。

下面是按照所需方式工作的代码片段:

代码语言:javascript
运行
复制
public void TypeWritter(string message, int delay, bool newLine = true)
{
    var player = new SoundPlayer
    {
        SoundLocation = @"C:\Users\Erick\Desktop\C#\CanizHospital\CanizHospital\typewriter-key-1.wav"
    };
    foreach (char c in message)
    {
        player.Play();
        Console.Write(c);
        Thread.Sleep(delay);
        player.Stop();
    }
    if (newLine)
    {
        Console.Write(Environment.NewLine);
        player.SoundLocation = @"C:\Users\Erick\Desktop\C#\CanizHospital\CanizHospital\typewriter-return-1.wav";
        player.PlaySync();
        //Thread.Sleep(delay); // Might not be necessary
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48311157

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档