C
C#13mo ago
AceChewy

❔ ✅ Using sound in C#

Could someone help me with adding a sound to my program. I'm trying to make a very basic timer which asks the user for a timer and once the time is set, it plays a sound
127 Replies
Pobiega
Pobiega13mo ago
You'll most likely want to use NAudio
AceChewy
AceChewy13mo ago
Would you mind elaborating please? As in how to implement NAudio
Pobiega
Pobiega13mo ago
Google "NAudio C#", find https://github.com/naudio/NAudio scroll down on mainpage to "Playing an Audio File from a Console application" see following code
using(var audioFile = new AudioFileReader(audioFile))
using(var outputDevice = new WaveOutEvent())
{
outputDevice.Init(audioFile);
outputDevice.Play();
while (outputDevice.PlaybackState == PlaybackState.Playing)
{
Thread.Sleep(1000);
}
}
using(var audioFile = new AudioFileReader(audioFile))
using(var outputDevice = new WaveOutEvent())
{
outputDevice.Init(audioFile);
outputDevice.Play();
while (outputDevice.PlaybackState == PlaybackState.Playing)
{
Thread.Sleep(1000);
}
}
AceChewy
AceChewy13mo ago
Ok, cool - now where would I place the location of the actual audio file "C:\Users\Ace\Desktop\mixkit-retro-game-emergency-alarm-1000.wav"
Pobiega
Pobiega13mo ago
I'd suggest you put it in your project folder, and set up a "copy to output directory" action for it so its always available locally to your project
AceChewy
AceChewy13mo ago
ok, makes sense
Pobiega
Pobiega13mo ago
then rename it to "alarm.wav" or something nicer to work with, and you're off to the races 🙂
AceChewy
AceChewy13mo ago
Do you know where I can find a tutorial to set up that action - very new to C# here Sounds good, thanks :)
Pobiega
Pobiega13mo ago
Easy. What are you using, visual studio? as in, not code.
AceChewy
AceChewy13mo ago
yh, I'm using Visual Studio
Pobiega
Pobiega13mo ago
okay, so copy the file into your project root directory then, in VS you should see the file in your solution explorer click it, then check the "properties" window there, under "Copy to Output" select" copy newer"
AceChewy
AceChewy13mo ago
ok For some reason the file isn't showing up even though I placed it in the project root directory
Pobiega
Pobiega13mo ago
show
AceChewy
AceChewy13mo ago
Pobiega
Pobiega13mo ago
ok, remove the search parameter ooooh i see it this is a .NET Framework project not a .NET Core meaning you are using a .NET version from... 2016-2017?
AceChewy
AceChewy13mo ago
I think I am, It's using .Net Version 4.7.2
Pobiega
Pobiega13mo ago
yep, thats indeed older than my children Any particular reason you are using the old versions? If not, I highly recommend upgrading
AceChewy
AceChewy13mo ago
Honestly, I wacthed a tutorial from about a year or two ago when setting up VStudio so that's probably why
Pobiega
Pobiega13mo ago
Alright, this is doable even on the old version, but you really really should upgrade
AceChewy
AceChewy13mo ago
Will do! Should I upgrade to .NET 7 or 6? I think there are some differences
Pobiega
Pobiega13mo ago
7
AceChewy
AceChewy13mo ago
I want to be using this when making projects from now on corrrect? • ASP.NET Core Runtime 7.0.9
AceChewy
AceChewy13mo ago
Also are these settings correct?
Pobiega
Pobiega13mo ago
uh, where did it even ask that? but yeah, thats the latest version of the runtime but you need the SDK to actually make programs the runtime is for running programs yes, but remove "enable docker"
AceChewy
AceChewy13mo ago
Ah ok, thanks for the heads up
Pobiega
Pobiega13mo ago
and thats a webapp, not a console app
AceChewy
AceChewy13mo ago
Better
Pobiega
Pobiega13mo ago
There we go
AceChewy
AceChewy13mo ago
I've also gone ahead and downloaded the appropriate SDK
Pobiega
Pobiega13mo ago
you might be more comfortable checking that checkbox 🙂 great I hope you made sure it was the x64 versions? a lot of people install x86 by mistake and then end up having issues
AceChewy
AceChewy13mo ago
I made sure
Pobiega
Pobiega13mo ago
excellent
AceChewy
AceChewy13mo ago
Just need to transfer my code now
AceChewy
AceChewy13mo ago
I'm getting some strange syntax error with my method at the bottom and something to do with nullability with the classes at the top - besides that all is good
Pobiega
Pobiega13mo ago
you have a nested main two mains.
AceChewy
AceChewy13mo ago
Ah My mistake You're referring to copy if newer correct?
Pobiega
Pobiega13mo ago
Yup
AceChewy
AceChewy13mo ago
Back to this Where does the path for the music file go in the part of code you shared?
Pobiega
Pobiega13mo ago
Have you added the nuget?
AceChewy
AceChewy13mo ago
I'm not sure whcih Nuget to add
AceChewy
AceChewy13mo ago
There are quite a few options
arion
arion13mo ago
<PackageReference Include="NAudio" Version="2.1.0" />
Look for one called NAudio or add it manually
AceChewy
AceChewy13mo ago
I'm guessing I want .Core
arion
arion13mo ago
Use the first option, NAudio.Core is their well, core library, it should be implicitly installed along with other dependencies of itself
Pobiega
Pobiega13mo ago
Aye, just instlal the top one
AceChewy
AceChewy13mo ago
All installed Now how to do I proceed?
Pobiega
Pobiega13mo ago
How do you think? Legitimate question.
AceChewy
AceChewy13mo ago
So, here's the code I need to use - my issue is not knowing where to place the path for the .wav file
Pobiega
Pobiega13mo ago
Look at the code. Try and figure it out there is really only one place that makes even the slighest amount of sense hell, the method parameter is actually called "fileName"
AceChewy
AceChewy13mo ago
my initial guess was WaveOutEvent()
Pobiega
Pobiega13mo ago
How so? What do you think WaveOutEvent does? and what do you think AudioFileReader does? Hint: one of these reads an audio file, the other plays the wave audio
AceChewy
AceChewy13mo ago
I'm guessing AudioFileReader, as the name suggests, reads the desired file
Pobiega
Pobiega13mo ago
sounds about right to me
arion
arion13mo ago
What Pobiega means is, if you don't try to figure it out yourself first it will be harder to learn. Since through trial and error you learn more than you usually would have learnt if you would have been given the answer verbatim, exploring what parameters you can feed it
Pobiega
Pobiega13mo ago
^ giving you the answer verbatim would be what we call spoonfeed (spoonfeeding) its frowned upon generally
AceChewy
AceChewy13mo ago
See that was my original guess but I thought for some reason that the WaveOutEvent makes more sense. Guess I should have looked at it a bit better and walked through the logic I mean I appreciate not straight up being told answers so not qualms here
Pobiega
Pobiega13mo ago
great.
AceChewy
AceChewy13mo ago
Thanks for the patience and taking the time to walk me through and help out
Pobiega
Pobiega13mo ago
no worries. its worth noting that Thread.Sleep() is a little intrusive, it actually freezes your entire program for the duration given its used here to prevent the program from finishing before the audio has finished playing
AceChewy
AceChewy13mo ago
Ah ok, good to know
Pobiega
Pobiega13mo ago
you can skip that, if your program isnt supposed to end directly after playing the audio
AceChewy
AceChewy13mo ago
Ok, it should be fine for this particular program
AceChewy
AceChewy13mo ago
But I am now struggling with this and I feel like I've missed something very obvious
Pobiega
Pobiega13mo ago
that path doesnt look right? TimerV2\TimerV2\TimerV2
AceChewy
AceChewy13mo ago
It should be
AceChewy
AceChewy13mo ago
There doesn't seem to be an executable file thoigh
Pobiega
Pobiega13mo ago
okay do you have any compilation errors?
AceChewy
AceChewy13mo ago
No Right, after scanning through, the problem seems to be an additional } at the end of the program
Pobiega
Pobiega13mo ago
that would indeed entirely prevent compilation
AceChewy
AceChewy13mo ago
Right I think that's it The interval is measured in seconds right or ms?
Pobiega
Pobiega13mo ago
hm? what interval?
arion
arion13mo ago
You can hover over the member to get more info about it
arion
arion13mo ago
Im like 99% sure Visual Studio has that feature
Pobiega
Pobiega13mo ago
it does indeed
AceChewy
AceChewy13mo ago
Where I ask the user for the duration of the timer
Pobiega
Pobiega13mo ago
oh dear me you hardcoded the absolute file path anyways? after all the effort we went through to NOT have to do that? 😄
AceChewy
AceChewy13mo ago
My bad, sorry
Pobiega
Pobiega13mo ago
and no Timer.Interval is in milliseconds, as arion pointed out also, be aware that Convert.ToInt is... not recommended hint: what does it do when I type "cheese" as my interval?
AceChewy
AceChewy13mo ago
TrySparse instead?
Pobiega
Pobiega13mo ago
correct
AceChewy
AceChewy13mo ago
I think this does the trick
Pobiega
Pobiega13mo ago
not really you dont use the return value from TryParse so you dont actually know if it succeeded or not Allow me to share one of my favorite static methods
public static T GetFromConsole<T>(string prompt, Func<T, bool>? validator = null) where T : IParsable<T>
{
while (true)
{
Console.Write(prompt);
if (T.TryParse(Console.ReadLine(), null, out var value))
{
if (validator?.Invoke(value) ?? true)
{
return value;
}

Console.WriteLine("Invalid value, try again.");
continue;
}

Console.WriteLine("Invalid format, try again.");
}
}
public static T GetFromConsole<T>(string prompt, Func<T, bool>? validator = null) where T : IParsable<T>
{
while (true)
{
Console.Write(prompt);
if (T.TryParse(Console.ReadLine(), null, out var value))
{
if (validator?.Invoke(value) ?? true)
{
return value;
}

Console.WriteLine("Invalid value, try again.");
continue;
}

Console.WriteLine("Invalid format, try again.");
}
}
Slap this badboy down and call it like int interval = GetFromConsole<int>("Enter your interval: "); and you are done
AceChewy
AceChewy13mo ago
I apparently need to express the type arguments explicitly
Pobiega
Pobiega13mo ago
okay, just slap on a <int> then 🙂
AceChewy
AceChewy13mo ago
I honestly have no clue where to put the int
arion
arion13mo ago
big brain 5Head
Pobiega
Pobiega13mo ago
int interval = GetFromConsole<int>("Enter your interval: "); generic type parameters always go after the method name
AceChewy
AceChewy13mo ago
Got to note that one down
arion
arion13mo ago
Multiple generic parameters are separated by an , so <int, bool>
AceChewy
AceChewy13mo ago
I wish it were that simple (for me), the audio isn't playing and I think it has something to do with the directory path maybe
Pobiega
Pobiega13mo ago
generic methods is a bit advanced for your current level, so don't worry about it 😛 just change the filepath to "alarm.wav" literally just that
AceChewy
AceChewy13mo ago
Still no audio playing though
Pobiega
Pobiega13mo ago
const string fileName = "blip.wav";

await using var audioFile = new AudioFileReader(fileName);
using var outputDevice = new WaveOutEvent();

outputDevice.Volume = 0.1f;

outputDevice.Init(audioFile);

Console.WriteLine("Playing sound.");

outputDevice.Play();

while (outputDevice.PlaybackState == PlaybackState.Playing)
{
await Task.Delay(1000);
}

Console.WriteLine("Done playing sound.");
const string fileName = "blip.wav";

await using var audioFile = new AudioFileReader(fileName);
using var outputDevice = new WaveOutEvent();

outputDevice.Volume = 0.1f;

outputDevice.Init(audioFile);

Console.WriteLine("Playing sound.");

outputDevice.Play();

while (outputDevice.PlaybackState == PlaybackState.Playing)
{
await Task.Delay(1000);
}

Console.WriteLine("Done playing sound.");
thats what I did here and it worked fine are you sure your interval/timer stuff is working? Number 1 good idea in programming is to test each part individually
AceChewy
AceChewy13mo ago
I normally do, but I kind of jumped the gun here I think I'm missing this (outputDevice.Volume = 0.1)
Pobiega
Pobiega13mo ago
thats not relevant as such I just like protecting my eardrums 😄 and I have in ear headphones it works fine without it, its just really loud
AceChewy
AceChewy13mo ago
I think that set of {} (yellow ones) are doing nothing here
AceChewy
AceChewy13mo ago
well not nothing, but they aren't supposed to be there anymore
Pobiega
Pobiega13mo ago
hard to tell without knowing what goes above it
AceChewy
AceChewy13mo ago
Pobiega
Pobiega13mo ago
no they absolutely do something you need to change up the syntax of your usings if you wanna get rid of that scope I'm using modern C# using declarations thats why my code didn't have them :p just add some Console.WriteLine("Sound should be playing now"); or somnething to the top of your method and see if its printing
AceChewy
AceChewy13mo ago
yup, your hunch was correct, nothing is printing
Pobiega
Pobiega13mo ago
goodthinking
arion
arion13mo ago
try doing timer.Start();
Pobiega
Pobiega13mo ago
oh dearie me I never bothered to read the timer code, as it wasn't relevant to the actual topic :p
arion
arion13mo ago
xD
AceChewy
AceChewy13mo ago
Right arion, you were right that did indeed change things
Pobiega
Pobiega13mo ago
tbh thou, wouldn't a PeriodicTimer be a lot easier?
AceChewy
AceChewy13mo ago
But the sound is still not playing
Pobiega
Pobiega13mo ago
var seconds = Helper.GetFromConsole<int>("Enter interval in seconds: ");
var interval = TimeSpan.FromSeconds(seconds);

var timer = new PeriodicTimer(interval);

while (await timer.WaitForNextTickAsync())
{
await PlaySound();
}
var seconds = Helper.GetFromConsole<int>("Enter interval in seconds: ");
var interval = TimeSpan.FromSeconds(seconds);

var timer = new PeriodicTimer(interval);

while (await timer.WaitForNextTickAsync())
{
await PlaySound();
}
thats my entire main method
Enter interval in seconds: 5 Playing sound. Done playing sound. Playing sound. Done playing sound. Playing sound. Done playing sound.
its really annoying 😄
AceChewy
AceChewy13mo ago
Overcomplicating things (and then not getting them) is my middlename
Pobiega
Pobiega13mo ago
Well... its not really fair to compare your code to mine I write C# for 40 hours a week and have done so for the last 20 years or so
AceChewy
AceChewy13mo ago
Yh, I'm aware
Pobiega
Pobiega13mo ago
PeriodicTimer came with .NET 6 so its fairly new, and didnt exist in .NET 4.7 that you were using an hour ago
AceChewy
AceChewy13mo ago
Doing 7 hours a week for 1 month isn't quite comparable. Though I have taken the long route with things a few times in the past I'm still annoyed by the fact the sound itself isn't palying
Pobiega
Pobiega13mo ago
Wanna jump on a screenshare and get it working?
arion
arion13mo ago
pretty sure its that part ngl
AceChewy
AceChewy13mo ago
Sure
arion
arion13mo ago
try changing it into timer.Elapsed += timedEvent;
Pobiega
Pobiega13mo ago
#dev-vc-1
AceChewy
AceChewy13mo ago
Thanks again for the taking the time to help
Pobiega
Pobiega13mo ago
np If you are done with this thread, please /close it
Accord
Accord13mo ago
Looks like nothing has happened here. I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server
More Posts
✅ Issues with method not being availableHello, I'm running latest version of .NET and latest version of EF Core and i'm trying to use bulk o✅ Content of .txt into LabelHello, I'm a beginner with C#, actualy i'm trying to past the content of a txt file into a Label or ❔ Blazor generic component "Type or namespace could not be found"Hello, In my blazor app, i have a generic component (with the use of `@typeparam T`). I have a page ❔ System.IO.FileLoadException for Microsoft.SqlServer.TypesI am working on an old project (.net 4.8) and updating the dependencies. One of these is `Microsoft.❔ blazor wont build from solution template riderhello everyone 🙂 noob here, i've been building blazor webassembly apps for a week it's been fine aASP.NET JSON conversion issuesHello, for some reason asp.net is not serializing my response object correctly, in my request I retu❔ Blazor - Event executed more than onceIt’s the first time I’m asking something on the net, so sorry if the formatting or the way the answe❔ Output from a command line app has extra characters when redirected to my applicationhere is the redirected output. It has these weird characters that are underlined. When running the c✅ Difficulty understanding Inheritance and where to use ConstructorHello people. I'm learning OOP and I've come across this problem. I'm creating a Football team creat❔ Linking folder from one project to anotherHi, i wanted to link folder from one project to another i accomplished it but i can't create new fil