Firstable I am not a PRO programmer but only a student who hava a little problem with an excelent library Midi-Dot-Net.
I use a Midi-Dot-Net library to write a simple application in Visual Studio in C# language. But I stuck on a very confusing problem.
I placed a little code into Form1.cs
public void NoteOn(NoteOnMessage msg) {
if (InvokeRequired) {
BeginInvoke(noteOnHandler, msg);
return;
}
inputStatusLabel.Text = String.Format("{0}", msg.Pitch);
String nutka = inputStatusLabel.Text;
if (nutka == "A0") {
clock.Schedule(new NoteOnMessage(outputDevice, Channel.Channel1, Pitch.A0, 80, 2));
}
}
So, I placed new String and called it nutka, and nutka will receive name of the pressed note on my USB MIDI Keyboard. Then I placed IF statment, and compared nutka to "A0" (first note on the keyboard).
Then if it's "A0" I pressed my outputDevice plays specific note. And it plays but it plays twice, one - when I press key (with note A0) on keyboard and second time - when I release that key.
I did a breakpoint on public void NoteOn(NoteOnMessage msg) and noticed that an application returns here twice and plays twice that note, still don't know why.
One more thing, there is a method public void NoteOff(NoteOffMessage message), but it seems not working.
I really can't figure it out, and I'm looking for any help.
UPDATE
...
UPDATE
...
UPDATE
Another problem appears (the first part was resolved thanks to CL and Chris Dunaway advice and step-by-step Justin explanation).
Thank you Justin :) i see life without any problems is not possible :)
With clock.Schedule i can play only the MIDI sound but i want to play example piano notes (wav file format) and in 4-5
weeks my college will help me recording my own piano sounds for every note. I also want to play them simultaneous.
I thought everything will be just fine and now... got problem with simultaneous playing. I was trying to check three possibilities:
1) I was trying to play piano sounds from basic notes library i have and use SoundPlayer for it:
SoundPlayer noteA0 = new SoundPlayer(Properties.Resources.A0);
noteA0.Play();
i use it for every note statement with different SoundPlayer name (depend on note name) and what i noticed is - i can't play notes simultaneously.
2) so i used next WMP library and WindowsMediaPlayer:
for example:
var noteA0 = new WMPLib.WindowsMediaPlayer();
noteA0.URL = #"c:\sounds\piano\A0.wav";
Ok... it plays simultaneous but it looks like the more notes i play or i just play a song the bigger latency i got and finnaly my programm stuck on playing anything...
3) i was trying to use Microsoft.DirectX.AudioVideoPlayback:
Audio noteA1 = new Audio(#"C:\sounds\piano\A1.wav");
noteA1.Play();
i started my programm, pressed a key and boom! crashed with an error message:
An unhandled exception of type 'System.BadImageFormatException' occurred in Midi.dll
Additional information: Could not load file or assembly 'Microsoft.DirectX.AudioVideoPlayback.dll' or one of its dependencies.
It is not a valid Win32 application. (Exception from HRESULT: 0x800700C1)
Of course i didn't forget to use:
using System.Media;
using Microsoft.DirectX.AudioVideoPlayback;
using Microsoft.DirectX;
Right now i have no idea what can i do more and again - i need a help of an experienced person :)
Expanding on CL.'s answer, here is the sequence of events that is probably happening:
You push a key on your MIDI keyboard which sends out a Note On message, with a Pitch of A0, and a velocity (the exact velocity may vary every time).
Your code receives this and, since it matches your if statement, sends out a Note On message, with a pitch of A0, and a velocity of 80.
Here's where it gets tricky. Some MIDI devices send a corresponding Note Off message with the same Pitch when you release the key. Other devices will send a second Note On message with the same Pitch, but with a Velocity of 0. These two types of message are (or should be) functionally equivalent, and each device can do either to stop a note playing (or even both). So,
You release the key on your keyboard which sends out a Note On message, with a Pitch of A0, and a Velocity of 0.
Your code receives this and, since it also matches your if statement, sends out a Note On message, with a pich of A0, and a velocity of 80.
Since a Note On with a Velocity of 0 is also a Note Off, what happens is your code is turning your keyboard's "Note Off" back into a Note On, thus playing the sound twice.
As Chris Dunaway suggested, you need to determine if a Note On is actually a "Note Off" by testing for a Velocity of 0.
if (nutka == "A0" && msg.Velocity != 0) {
clock.Schedule(new NoteOnMessage(outputDevice, Channel.Channel1, Pitch.A0, 80, 2));
}
The MIDI 1.0 Detailed Specification says:
MIDI provides two roughly equivalent means of turning off a note (voice). A note may be turned off either by sending a Note-Off message for the same note number and channel, or by sending a Note-On message for that note and channel with a velocity value of zero. The advantage to using "Note-On at zero velocity" is that it can avoid sending additional status bytes when Running Status is employed.
Due to this efficiency, sending Note-On messages with velocity values of zero is the most commonly used method. However, some keyboard instruments implement release velocity where a Note-Off code (8nH) accompanied by a "velocity off" byte is used. A receiver must be capable of recognizing either method of turning off a note, and should treat them identically.
Related
I'm working on some kind of 2D sandbox game in "Unity". In this game, you can create your battle figure like "robocraft" .
Details;
You can create your battleship on the another interface. if click "play", works "save" and "dontdestroyonload". Main Part is fixed. Other parts are child and in same tag with main part if they are unified eachother and main part. I used for this "collision stay".
And i want to create physics like in this picture;
[1]
[1]: https://i.stack.imgur.com/OhMMk.jpg
long story short; If below or above green part stay still, grey parts stay still because of connection but destroy both of them, all grey part must destroy.
I'm trying to use "flood fill algorithm" but I didn't know how to integrate to my codes.
Do you know any other solutions or can you give any example about "flood fill" for kind of this problems?
Already thanks for the people who trying to help.
My take on flood filled algorithm for your case would look like this:
Determine neighbours for each part. It will be maximum of 4 parts, or 8 if adjacency by corners also counts.
Create a list of neighbours and you can use OnCollisionStay to populate each list with neighbours.
When battleship is hit, this is where algorithm starts.
Create a Queue<Part> (or whatever collection suits you)
For each destroyed part
1.1) For each destroyed part's neighbours
1.1.1) Push its neighbours to the queue
1.1.2) Take the the first element from the queue. Mark it with flag as checked, and push it to the new checkedQueue.
1.1.3) Check if the part in question is a base part. If it is, it means there's a connection from neighbour of the destroyed part to the base, and those parts don't need to be destroyed. Exit the loop.
1.1.4) If it's not, push it's neighbours to the initial queue.
Continue with checking all parts. If you run out parts in the queue without exiting, it means there's no connection to the main part, and all parts on checking queue should be destroyed.
Obviously don't check or push parts that already have checked or destroyed flags. Be careful not to analyze all damaged part's neighbours at once, or you will end up with all parts connected to the core :) Also you might need to clear queues at appropriate times as well as reset flags when needed.
Hope you can read through that pseudo code, formatting on mobile is a challenging task. It probably isn't the most optimised code in the world, but it can serve as a good start.
I have a project where audio is recorded at several sources, and the goal is to process X (user-defined) seconds of it through various methods (DSP as well as speech-to-text).
I'm using a MixingSampleProvider to collect all the sources into one "provider." I'm passing this to a NotifyingSampleProvider because it raises an event at each sample, and then passing that sample to my class that does the processing. I'm adding the float the NotifyingSampleProvider produces to the end of my "X second window" array (using Array.Copy to create a temp array with all but that last value, adding that last value, and copying the temp array back to the original) which I use for processing.
The obvious problem here is that it notifies (and that I'm locking and adding to the "X second window" array) for every single sample, or 44100 times a second. This leads to the audio being pretty much constantly locked so it can't be processed. There's got to be a more performant way to deal with this.
The one idea I had was a BufferedWaveProvider that doesn't get read from anywhere else, so it's always full (with DiscardOnOverflow = true of course). However A) this still requires a NotifyingSampleProvider to add to it periodically (you can't pass a provider to the BufferedWaveProvider for it to automatically read from) and I'd like to get away from such frequent (44100 Hz) function calls, and B) I understand that there's a limit to the BufferDuration length, which might be too small of a window (I don't recall what the limit is and I can't find anything online saying what it is).
How might I solve this problem? Using NAudio, how to I keep the last X seconds of audio accessible to a separate class at any time without using the NotifyingSampleProvider?
I will begin by saying that I'm very new to C# and Unity, so apologies in advance if I am lacking what would be considered common knowledge. Also, I have checked other questions on here and have not found any answers that particularly solved my specific issue. If there is one however, I would appreciate being pointed towards it.
Anyway, I am trying to write some code that will play a sound when a key is held down and will stop playing when the key is released. Different keys will play different sounds, so the GetKeyUp() function should apply to whatever key is currently being pressed.
I have declared a string for inputKey, and inputKey is assigned whatever key is being pressed, and is then passed through to an if statement containing the GetKeyUp() function. I have tried numerous small variations of this method but the one I am currently using has been the only way that hasn't yielded an error message (although the code still doesn't work)
public string inputKey;
else if (Input.GetKeyDown(KeyCode.S))
{
freq = 293.66;
gain = volume;
}
inputKey = (Input.inputString).ToUpper();
if (Input.GetKeyUp(KeyCode.inputKey));
{
gain = 0;
}
So in the example above, when the key S is pressed, the sound is played. The inputKey is being displayed as 'S' so I would expect 'Input.GetKeyUp(KeyCode.inputKey)' to be the equivalent of 'Input.GetKeyUp(KeyCode.S' and the sound to stop playing, yet this is not the case and the sound continues to play.
Any help or advice would be greatly appreciated, thanks.
I would use Input.GetKey() instead.
Rather than checking "is S down? start playing the S sound. Is A down? start playing the A sound. Did any key get released? What key was it? stop playing that sound" I would simply check each key's current state and start or stop the sound based on that state.
E.g.
soundOnS.gain = Input.GetKey(KeyCode.S) ? volume : 0;
Your current approach can not, and never could, adequately handle what happens if someone presses down on multiple keys at the same time: when they lift up one finger, releasing one key (but not the other!) what sound should be playing?
For the challenge and educational gain, i am currently trying to make a simple game in the console window. I use a very primitive "locked" framerate system as such:
using System.Threading;
// ...
static private void Main(string[] args)
{
AutoResetEvent autoEvent = new AutoResetEvent(false);
Timer timer = new Timer(Update);
timer.Change(0, GameSpeed);
autoEvent.WaitOne();
}
So, a timer ticks every GameSpeed miliseconds, and calls the method Update().
The way that i have understood input in the console window so far is as follows:
The console application has a "queue" where it stores any keyboard input as metadata + an instance of a ConsoleKey enum. The user can add to this queue at any time. If the user holds down, say A, it will add A every computer frame. That is, the actual fastest amount the computer can do, not the locked frames i am working with.
Calling Console.Readkey() will remove and return the first element on this list. Console.KeyAvailable returns a bool indicating whether the list is empty.
If GameSpeedis set to anything higher than 400 everything consistently works fine. The below image displays the results of some Console.WriteLine() debug messages that give the amount of keyboard inputs detected in this locked/custom frame, using the following code:
int counter = 0;
while (Console.KeyAvailable) { counter++; Console.ReadKey(true); }
Console.WriteLine(counter);
Results
I use only the A key. I hold it for some time, then release it again. The GameSpeed is set to 1000. As expected, the first frames give low numbers as i might start pressing half into the frame, and so too with the last frames, as i might release the A early.
Now, the exact same experiment but with a GameSpeed of only 200
As you can see, i've marked the places i begun pressing with yellow. It always, perfectly gets the first frame. But then theres either one, two, or three frames where it acts as if it has gotten no inputs, but then after those frames it's fine and gets around 7 inputs pr frame.
I recognize that you are not supposed to make games in the console window. It is not made for scenarios like this. That does not however eliminate the possibility that there is some specific, logical reason this happens, that i might be able to fix. So, concretely the question is: can anyone provide some knowledge / ideas of why this happens?
If computer specs are needed, just say so in the comments and i'll add them.
Edit:
I think i have found the cause of this error, and it is windows keyboard repeat delay. While you can change this in the control panel, i have searched the web and found no examples of how you would change it in a c# application. The question then boils down to: how do you change windows keyboard repeat delay?
I'm writing a little app that's pretty much a sequencer (8 bit synths) I have a formula which converts a note to its corresponding frequency:
private float returnFrequency(Note note)
{
return (float)(440 * Math.Pow(TwoToTheTwelfthRoot, (note.SemitonesFromC0 - 57)));
}
Basically, what I'm trying to do is play a generated tone (sine, square, saw, etc) with this frequency, so it's audible through the speakers. Does XNA have any support for this? Or would I have to use an additional library?
I do not want to import 80+ samples of a sine wave at different frequencies through the Content Pipeline just so I could play tones with different frequencies.
For those of you who requested for the link, and for the future peoples who might need it:
http://www.david-gouveia.com/creating-a-basic-synth-in-xna-part-i/
He first goes through the dynamic sound instance, then goes to another level by showing you how to create voices (allowing a sort of 'play piano with your keyboard' type thing).
Funny thing is, David Gouveia has a StackExchange account, so I wouldn't be surprised if I get any notification from him at all, nor if some people recognized him.