C
C#17mo 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
Pobiega17mo ago
You'll most likely want to use NAudio
AceChewy
AceChewyOP17mo ago
Would you mind elaborating please? As in how to implement NAudio
Pobiega
Pobiega17mo 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
AceChewyOP17mo 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
Pobiega17mo 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
AceChewyOP17mo ago
ok, makes sense
Pobiega
Pobiega17mo ago
then rename it to "alarm.wav" or something nicer to work with, and you're off to the races 🙂
AceChewy
AceChewyOP17mo ago
Do you know where I can find a tutorial to set up that action - very new to C# here Sounds good, thanks :)
Pobiega
Pobiega17mo ago
Easy. What are you using, visual studio? as in, not code.
AceChewy
AceChewyOP17mo ago
yh, I'm using Visual Studio
Pobiega
Pobiega17mo 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
AceChewyOP17mo ago
ok For some reason the file isn't showing up even though I placed it in the project root directory
Pobiega
Pobiega17mo ago
show
AceChewy
AceChewyOP17mo ago
Pobiega
Pobiega17mo 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
AceChewyOP17mo ago
I think I am, It's using .Net Version 4.7.2
Pobiega
Pobiega17mo ago
yep, thats indeed older than my children Any particular reason you are using the old versions? If not, I highly recommend upgrading
AceChewy
AceChewyOP17mo ago
Honestly, I wacthed a tutorial from about a year or two ago when setting up VStudio so that's probably why
Pobiega
Pobiega17mo ago
Alright, this is doable even on the old version, but you really really should upgrade
AceChewy
AceChewyOP17mo ago
Will do! Should I upgrade to .NET 7 or 6? I think there are some differences
Pobiega
Pobiega17mo ago
7
AceChewy
AceChewyOP17mo ago
I want to be using this when making projects from now on corrrect? • ASP.NET Core Runtime 7.0.9
AceChewy
AceChewyOP17mo ago
Also are these settings correct?
Pobiega
Pobiega17mo 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
AceChewyOP17mo ago
Ah ok, thanks for the heads up
Pobiega
Pobiega17mo ago
and thats a webapp, not a console app
AceChewy
AceChewyOP17mo ago
Better
Pobiega
Pobiega17mo ago
There we go
AceChewy
AceChewyOP17mo ago
I've also gone ahead and downloaded the appropriate SDK
Pobiega
Pobiega17mo 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
AceChewyOP17mo ago
I made sure
Pobiega
Pobiega17mo ago
excellent
AceChewy
AceChewyOP17mo ago
Just need to transfer my code now
AceChewy
AceChewyOP17mo 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
Pobiega17mo ago
you have a nested main two mains.
AceChewy
AceChewyOP17mo ago
Ah My mistake You're referring to copy if newer correct?
Pobiega
Pobiega17mo ago
Yup
AceChewy
AceChewyOP17mo ago
Back to this Where does the path for the music file go in the part of code you shared?
Pobiega
Pobiega17mo ago
Have you added the nuget?
AceChewy
AceChewyOP17mo ago
I'm not sure whcih Nuget to add
AceChewy
AceChewyOP17mo ago
There are quite a few options
arion
arion17mo ago
<PackageReference Include="NAudio" Version="2.1.0" />
Look for one called NAudio or add it manually
AceChewy
AceChewyOP17mo ago
I'm guessing I want .Core
arion
arion17mo ago
Use the first option, NAudio.Core is their well, core library, it should be implicitly installed along with other dependencies of itself
Pobiega
Pobiega17mo ago
Aye, just instlal the top one
AceChewy
AceChewyOP17mo ago
All installed Now how to do I proceed?
Pobiega
Pobiega17mo ago
How do you think? Legitimate question.
AceChewy
AceChewyOP17mo 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
Pobiega17mo 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
AceChewyOP17mo ago
my initial guess was WaveOutEvent()
Pobiega
Pobiega17mo 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
AceChewyOP17mo ago
I'm guessing AudioFileReader, as the name suggests, reads the desired file
Pobiega
Pobiega17mo ago
sounds about right to me
arion
arion17mo 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
Pobiega17mo ago
^ giving you the answer verbatim would be what we call spoonfeed (spoonfeeding) its frowned upon generally
AceChewy
AceChewyOP17mo 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
Pobiega17mo ago
great.
AceChewy
AceChewyOP17mo ago
Thanks for the patience and taking the time to walk me through and help out
Pobiega
Pobiega17mo 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
AceChewyOP17mo ago
Ah ok, good to know
Pobiega
Pobiega17mo ago
you can skip that, if your program isnt supposed to end directly after playing the audio
AceChewy
AceChewyOP17mo ago
Ok, it should be fine for this particular program
AceChewy
AceChewyOP17mo ago
But I am now struggling with this and I feel like I've missed something very obvious
Pobiega
Pobiega17mo ago
that path doesnt look right? TimerV2\TimerV2\TimerV2
AceChewy
AceChewyOP17mo ago
It should be
AceChewy
AceChewyOP17mo ago
There doesn't seem to be an executable file thoigh
Pobiega
Pobiega17mo ago
okay do you have any compilation errors?
AceChewy
AceChewyOP17mo ago
No Right, after scanning through, the problem seems to be an additional } at the end of the program
Pobiega
Pobiega17mo ago
that would indeed entirely prevent compilation
AceChewy
AceChewyOP17mo ago
Right I think that's it The interval is measured in seconds right or ms?
Pobiega
Pobiega17mo ago
hm? what interval?
arion
arion17mo ago
You can hover over the member to get more info about it
arion
arion17mo ago
Im like 99% sure Visual Studio has that feature
Pobiega
Pobiega17mo ago
it does indeed
AceChewy
AceChewyOP17mo ago
Where I ask the user for the duration of the timer
Pobiega
Pobiega17mo 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
AceChewyOP17mo ago
My bad, sorry
Pobiega
Pobiega17mo 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
AceChewyOP17mo ago
TrySparse instead?
Pobiega
Pobiega17mo ago
correct
AceChewy
AceChewyOP17mo ago
I think this does the trick
Pobiega
Pobiega17mo 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
AceChewyOP17mo ago
I apparently need to express the type arguments explicitly
Pobiega
Pobiega17mo ago
okay, just slap on a <int> then 🙂
AceChewy
AceChewyOP17mo ago
I honestly have no clue where to put the int
arion
arion17mo ago
big brain 5Head
Pobiega
Pobiega17mo ago
int interval = GetFromConsole<int>("Enter your interval: "); generic type parameters always go after the method name
AceChewy
AceChewyOP17mo ago
Got to note that one down
arion
arion17mo ago
Multiple generic parameters are separated by an , so <int, bool>
AceChewy
AceChewyOP17mo 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
Pobiega17mo 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
AceChewyOP17mo ago
Still no audio playing though
Pobiega
Pobiega17mo 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
AceChewyOP17mo ago
I normally do, but I kind of jumped the gun here I think I'm missing this (outputDevice.Volume = 0.1)
Pobiega
Pobiega17mo 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
AceChewyOP17mo ago
I think that set of {} (yellow ones) are doing nothing here
AceChewy
AceChewyOP17mo ago
well not nothing, but they aren't supposed to be there anymore
Pobiega
Pobiega17mo ago
hard to tell without knowing what goes above it
AceChewy
AceChewyOP17mo ago
Pobiega
Pobiega17mo 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
AceChewyOP17mo ago
yup, your hunch was correct, nothing is printing
Pobiega
Pobiega17mo ago
goodthinking
arion
arion17mo ago
try doing timer.Start();
Pobiega
Pobiega17mo ago
oh dearie me I never bothered to read the timer code, as it wasn't relevant to the actual topic :p
arion
arion17mo ago
xD
AceChewy
AceChewyOP17mo ago
Right arion, you were right that did indeed change things
Pobiega
Pobiega17mo ago
tbh thou, wouldn't a PeriodicTimer be a lot easier?
AceChewy
AceChewyOP17mo ago
But the sound is still not playing
Pobiega
Pobiega17mo 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
AceChewyOP17mo ago
Overcomplicating things (and then not getting them) is my middlename
Pobiega
Pobiega17mo 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
AceChewyOP17mo ago
Yh, I'm aware
Pobiega
Pobiega17mo 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
AceChewyOP17mo 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
Pobiega17mo ago
Wanna jump on a screenshare and get it working?
arion
arion17mo ago
pretty sure its that part ngl
AceChewy
AceChewyOP17mo ago
Sure
arion
arion17mo ago
try changing it into timer.Elapsed += timedEvent;
Pobiega
Pobiega17mo ago
#dev-vc-1
AceChewy
AceChewyOP17mo ago
Thanks again for the taking the time to help
Pobiega
Pobiega17mo ago
np If you are done with this thread, please /close it
Accord
Accord17mo 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