{"id":28225961,"url":"https://github.com/xmaman/soundengineexamples","last_synced_at":"2025-06-13T00:31:38.923Z","repository":{"id":288399908,"uuid":"967935296","full_name":"XMAMan/SoundEngineExamples","owner":"XMAMan","description":"Demoapplication for XMAMan.SoundEngine-NuGet-Package","archived":false,"fork":false,"pushed_at":"2025-04-17T10:12:40.000Z","size":8627,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-05-18T11:09:54.355Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/XMAMan.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-04-17T08:28:50.000Z","updated_at":"2025-04-17T10:12:43.000Z","dependencies_parsed_at":"2025-04-17T23:52:07.558Z","dependency_job_id":"35776305-e34d-4a14-af4f-4752fcfeff97","html_url":"https://github.com/XMAMan/SoundEngineExamples","commit_stats":null,"previous_names":["xmaman/soundengineexamples"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/XMAMan/SoundEngineExamples","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/XMAMan%2FSoundEngineExamples","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/XMAMan%2FSoundEngineExamples/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/XMAMan%2FSoundEngineExamples/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/XMAMan%2FSoundEngineExamples/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/XMAMan","download_url":"https://codeload.github.com/XMAMan/SoundEngineExamples/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/XMAMan%2FSoundEngineExamples/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259554927,"owners_count":22875899,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-05-18T11:09:53.052Z","updated_at":"2025-06-13T00:31:38.913Z","avatar_url":"https://github.com/XMAMan.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SoundEngine-Examples\n\nThis project shows how to use the XMAMan.SoundEngine-NuGet-Package. \n\nThe XMAMan.SoundEngine-NuGet-Package can be used for creating sounds in your games, for creating a audiorecorder or creating a audioplayer.\n\n* Usecases if you want to create a game:\n\t* case 1: playing backgroundmusic. Example: [marioUnderground.mp3](https://github.com/XMAMan/SoundEngineExamples/raw/refs/heads/main/Data/SoundExamples/marioUnderground.mp3)\n\t* case 2: play tones that can be held indefinitely and where the frequency is adjustable. Example: [movingDownSound.wma](https://github.com/XMAMan/SoundEngineExamples/raw/refs/heads/main/Data/SoundExamples/movingDownSound.wma)\n\t* case 3: play tones with a predefined length created by a oscillator-signal-source. Example: [hitGroundSound.wma](https://github.com/XMAMan/SoundEngineExamples/raw/refs/heads/main/Data/SoundExamples/hitGroundSound.wma)\n\t* case 4: play a simple mp3/wma/wav-file\n\n* Usecases if you want to create a audiorecorder:\n\t* case 5: use the microphone and change your voice by using effects like hall/delay or sound like a robot. Example: [RobotAndHallEffect.mp3](https://github.com/XMAMan/SoundEngineExamples/raw/refs/heads/main/Data/SoundExamples/RobotAndHallEffect.mp3)\n\t\n* Usecases if you want to create a audioplayer:\n\t* case 6: play a audiofile and visualize the frequency bands\n\nTo use this NuGet-Package, you need the MusicMachine-editor where you define your songs. This editor can be found here: [MusicMachine.exe](https://github.com/XMAMan/SoundEngineExamples/tree/main/MusicMachine)\n\nThis editor is needet for creating *.music-files, which can be used from the XMAMan.SoundEngine-NuGet-Package for playing music.\n\nThe project from here contains three wpf-projects to show how to use all cases. For case 1 to 4 there is the AudioOutput-project which looks like this:\n\n![AudioOutputProject.jpg](https://raw.githubusercontent.com/XMAMan/SoundEngineExamples/refs/heads/main/Data/Images/AudioOutputProject.jpg)\n\nYou can create with the mouse red balls, which are moving up or down and creating sounds during this.\n\nFor case 5 there is the AudioInput-project: ![AudioInputProject.jpg](https://raw.githubusercontent.com/XMAMan/SoundEngineExamples/refs/heads/main/Data/Images/AudioInputProject.jpg)\n\nand case 6 is shown by the AudioPlayer-project: ![AudioPlayer.jpg](https://raw.githubusercontent.com/XMAMan/SoundEngineExamples/refs/heads/main/Data/Images/AudioPlayer.jpg)\nwhich can play and visualize an audiofile.\n\n\n\n\n# Usecases if you want to create a game\n\n\n## Case 1: playing backgroundmusic\n\n\n### Case 1 Step 1: Define the backgroundmusic in the MusicMachine-Editor to create a *.music-file\n\nIf you want to play background music, then you can use a midi File as starting point and modify this file or you create your own songs by defining the notes and instruments by your own.\n\nIn our case we want to use a midiFile as starting-point and modify this file.\n\nDownload the midiFile from this exampleproject from here and save it in a local folder on your system: [Super Mario Galaxy - Retro Theme 2.mid](https://github.com/XMAMan/SoundEngineExamples/raw/refs/heads/main/Data/Super%20Mario%20Galaxy%20-%20Retro%20Theme%202.mid)\n\nStart at first the MusicMachine.exe and click in the contextbar on \"Load mp3/midi/music-File\" (1), select *.mid as filetype (2), select the mid-file(3) and click on open (4).\n\n![LoadMidiFile.jpg](https://raw.githubusercontent.com/XMAMan/SoundEngineExamples/refs/heads/main/Data/Images/LoadMidiFile.jpg)\n\nThe red rectangles are the notes from this song. You can here the original-midi-sound by pressing the \"Play Midi\"-Button (see (1) in the image). With (2) you stop the original-midi-output.\nWith the \"IsPlaying\"-checkbox (3) you start the playback by using the synthesizer. (4) will change the volume. Durring the playback you see that the blue line is moving forward. This is the actual\nplayposition. If you activate the AutoLoop-checkbox (5), then the blue line will jump automatically to the start if it reached the end of the song. \n\n![background1.jpg](https://raw.githubusercontent.com/XMAMan/SoundEngineExamples/refs/heads/main/Data/Images/background1.jpg)\n\nThis is your music-file after loading the mid-file: [background1.music](https://github.com/XMAMan/SoundEngineExamples/raw/refs/heads/main/Data/background1.music)\n\nThe speed from this song is slow so we increase the KeyStrokeSpeed with the slider (6) a little bit. Also the pitch from the song is very high so we will bring it down by 4 octaves by pressing \nbutton (7) 4 times.\n\nThis two changes produces a song that sounds like this: [background2.mp3](https://github.com/XMAMan/SoundEngineExamples/raw/refs/heads/main/Data/SoundExamples/background2.mp3)\n\nThis is your music-file after KeyStrokeSpeed-increase and octave-shift: [background2.music](https://github.com/XMAMan/SoundEngineExamples/raw/refs/heads/main/Data/background2.music)\n\nThe next change will be the keydown-speed from a single Piano Key Press. Move the AttackTime-Slider (8) completly down and the Decay-Time-Slider (9) is only a little bit over zero. This two \nchanges will increase the keydown-speed. The next change is the sustain volume-change by moving slider (10) down. This ensures that the sound is less sustained. \n\nWe are using a rectangle-signal at the moment. With the pulsewidth-slider (11) can we change the form from this signal. If we move this slider a little bit up then it sounds better.\nThe Count-Slider (12) defines, how many rectangle-signals are used. Move this slider down so we are only using one signal-source. Increase a little bit the SUB-Slider (13). This will add a second\nrectangle-signalsource but with a lower pitch. This is our bass. \n\nYour settings should now look like this:\n\n![background3.jpg](https://raw.githubusercontent.com/XMAMan/SoundEngineExamples/refs/heads/main/Data/Images/background3.jpg)\n\nAnd produces a sound like this:\n\n[background3.mp3](https://github.com/XMAMan/SoundEngineExamples/raw/refs/heads/main/Data/SoundExamples/background3.mp3)\n\nThis is your music-file after changing PW, Count, SUB, A,D,S: [background3.music](https://github.com/XMAMan/SoundEngineExamples/raw/refs/heads/main/Data/background3.music)\n\nFor the high chords we want to use a different instrument. To do this we add the the midi-File again and split the song into two instruments.\n\nPress at first on the \"Add Midi-File\"-Button (1) and change the Y-Zoom-Slider (2) which will only change the visual appearance. So both sequencer should be visible. Use also the\nZoom-Checkbox (3) which will fit the notes into the view.  The blue marked notes are the accords from this song and we want to use a other instrument for this notes.\n\n![background4.jpg](https://raw.githubusercontent.com/XMAMan/SoundEngineExamples/refs/heads/main/Data/Images/background4.jpg)\n\nThis is your music-file after adding the mid-file again as second sequencer: [background4.music](https://github.com/XMAMan/SoundEngineExamples/raw/refs/heads/main/Data/background4.music)\n\nMark the notes (blue marked in the image) block by block by holding the left mouse down and select with a selectionrectangle the accord-notes in the upper sequencer. After selection press the delete-key to\nremove the selected notes. Do this for every accord-note-block. Do this also for all not-accord-notes in the second sequencer. Then you should get this result:\n\n![background5.jpg](https://raw.githubusercontent.com/XMAMan/SoundEngineExamples/refs/heads/main/Data/Images/background5.jpg)\n\nThis is your music-file after removing in the first sequencer the blue marked accord-notes and in the second sequencer the not-accord-notes: [background5.music](https://github.com/XMAMan/SoundEngineExamples/raw/refs/heads/main/Data/background5.music)\n\nIf you right-click on the sequencer then you see, that the green border is changing so you see, that this sequencer is selected now. You will also see, that the settings in the upper area will \nchange, if you switch between the upper and lower sequencer. \n\nThe next step is now to define the instrument for the accord-notes. Select with a mouse-right-click the second sequencer. For this sequencer we will use a Triangle-Signal. \n\nUse the signal-source-combobox (1) and select \"Triangle\" and we change again the pitch by two octaves down by pressing Button (2) two times. For the attack-time (3) we use again zero and the \ndecaytime (4) becomes also a low value. The sustain-volume (5) should now a little bit higher then for the first sequencer because this are accords here. To get a flutter effect we use the \namplitude-low-frequency-oscillator (6) and change the frequence for this oscillator a little bit (7).\n\nAll your settings should now look like this for the second sequencer:\n\n![background6.jpg](https://raw.githubusercontent.com/XMAMan/SoundEngineExamples/refs/heads/main/Data/Images/background6.jpg)\n\nAnd produce this song:  [background6.mp3](https://github.com/XMAMan/SoundEngineExamples/raw/refs/heads/main/Data/SoundExamples/background6.mp3)\n\t\t\t\t\t\nSave now this file as a *.music-file by pressing the \"Save\"-Button in the upper right area. You can find the file from this example here:\n\n[background6.music](https://github.com/XMAMan/SoundEngineExamples/raw/refs/heads/main/Data/background6.music)\n\n### Case 1 Step 2: Use the *.music-file in your game\n\nFor this step: Open the AudioOutput-project from here: https://github.com/XMAMan/SoundEngineExamples/tree/master/Source/SoundEngineExamples.sln\n\nIf you now want to use the *.music-file in your game-project you have to use the XMAMan.SoundEngine-NuGet-Package and create a SoundGenerator-object. This object will start intern a audio-timer which \nwill produce the sound. The SoundGenerator-class implements the IDisposable-interface so you have to call the Dispose-method after receiving the Windows.Closed-event. With AddMusicFile you will load\nthe *.music-file into the memory and get a IMusicFileSnipped-object, were can control the playback from the backGround music.\n\n```csharp\nclass ViewModel : IDisposable\n{\n\tprivate SoundGenerator soundGenerator;\n\tprivate IMusicFileSnipped backGroundMusic;    // This controls the background music\n\t\n\tpublic ViewModel()\n\t{\n\t\tthis.soundGenerator = new SoundGenerator();\n\t\t\n\t\tthis.backGroundMusic = soundGenerator.AddMusicFile(WorkingDirectory + \"background6.music\");\t\t\n\t\t\n\t\tthis.backGroundMusic.Volume = 0.5f        // 0..1 here you can change the volume from you backGroundMusic\n\t\tthis.backGroundMusic.AutoLoop = true;     // start the playback again if the end is reached\n\t\tthis.backGroundMusic.KeyStrokeSpeed = 2;  // play with duplicated speed\n\t\tthis.backGroundMusic.KeyShift = -1;\t\t  // decrease the pitch by one octave\n\t\t\n\t\tthis.backGroundMusic.Play();              // start playback \n\t}\n\t\n\tpublic void Dispose()\n\t{\n\t\tthis.soundGenerator.Dispose(); \t\t\t  // Destroy the AudioTimer inside from this object\n\t}\n}\n```\n\n## Case 2: play tones that can be held indefinitely and where the frequency is adjustable\n\n\n### Case 2 Step 1: Define the instrument in the MusicMachine-Editor to create a *.music-file\n\nIn our next case we want to simulate a ball, which is falling down. Durring the movement there should be a sound, where the pitch is changing. This type of sound have no predefined length because \nwe don't now how far will the ball falling.\nTo define how such a sound sounds like we use again the MusicMachine-Editor and create again a *.music-file but now we don't have to define any notes. Start at first the \n[MusicMachine.exe](https://github.com/XMAMan/SoundEngineExamples/tree/main/MusicMachine) and click on \"Create new session\" (1) in the context bar and then on ok (2) in the dialog.\n\n![CreateNewSession.jpg](https://raw.githubusercontent.com/XMAMan/SoundEngineExamples/refs/heads/main/Data/Images/CreateNewSession.jpg)\n\nWe will use a Triangle-Signal (1) and FreqRamp-Effect (2). This effect will automatically decrease the pitch. Move the Ramp-Slider (3) a little bit down to increase to pitch-down-speed. \nWith the Test-Tone-Slider (4) we define the starting-frequency. Move this slider a little bit left the decrease the starting value. Press the \"Play Tone\"-Button and hold it to hear the sound.\n\n![movingBall1.jpg](https://raw.githubusercontent.com/XMAMan/SoundEngineExamples/refs/heads/main/Data/Images/movingBall1.jpg)\n\nSee: [movingBall1.music](https://github.com/XMAMan/SoundEngineExamples/raw/refs/heads/main/Data/movingBall1.music)\n\nIf the ball is created with a left click, then it should move down and play the just defined sound. If the user use the right mouse then the ball should fly up and for this case we want to define a \nother sound, where the pitch goes up. We will also save this second sound in the same *.music-file. To do so click on \"Add Empty Sequenzer\" (1) in the right top window area and then right click\non the second sequencer (2) the mark this. We use the Triangle-Signal (3) again and also the FreqRamp-Effect (4). But now we move the Ramp-Slider (5) a little bit up which will increase the pitch\ndurring playback.\n\n![movingBall2.jpg](https://raw.githubusercontent.com/XMAMan/SoundEngineExamples/refs/heads/main/Data/Images/movingBall2.jpg)\n\nYou can test the second sound by clicking on the \"Play Tone\"-Button again. With the Slider below (6) you define the start-frequency. A better way of starting the Test-tone-playback is pressing \"A\" for the first \nsequencer and \"S\" for the second sequencer. Hold this keys pressed.\n\nIf you hold \"A\" then the moving-down-sound sounds like this: [movingDownSound.wma](https://github.com/XMAMan/SoundEngineExamples/raw/refs/heads/main/Data/SoundExamples/movingDownSound.wma)\nIf you hold \"S\" then the moving-up-sound sounds like this: [movingUpSound.wma](https://github.com/XMAMan/SoundEngineExamples/raw/refs/heads/main/Data/SoundExamples/movingUpSound.wma)\n\nHold the \"S\"-key pressed and then change the Count-Slider (7) a little bit up to increase the signal-source-count and the Pitch-Slider (8) a little bit down. Each signal-source will use a slightly \nmodified frequency. Change also die FreqRamp-Effect (4) durring holding \"A\" or \"S\" to here how the sound is changing durring playback. \n\nFor the moving-up-sound we will also use the Amplitude-Low-Frequency-Oscillator (9) with a low frequency (10). You can change from each sequencer his own soundvolume by using the slider on the left \nside from the sequencers (11).\n\nThis is our created music-file: [movingBall2.music](https://github.com/XMAMan/SoundEngineExamples/raw/refs/heads/main/Data/movingBall2.music)\n\n### Case 2 Step 2: Use the *.music-file in your game\n\nWe have now a *.music-file with two different instruments. To use this in code use again the SoundGenerator-object but instead of using the AddMusicFile-method we are using AddSynthSoundCollection.\nThis method returns a IFrequenceToneSnipped-array with two items in our case because we have defined two sequencers. \n\nThe following example show, how to read the music-file and start the playback from a tone with no predefined length. You have to call Stop to end the playback.\n\n```csharp\nclass ViewModel : IDisposable\n{\n\tprivate SoundGenerator soundGenerator;\n\tprivate IMusicFileSnipped backGroundMusic;    // This controls the background music\n\t\n\tpublic ViewModel()\n\t{\n\t\tthis.soundGenerator = new SoundGenerator();\t\n\t\t\n\t\tvar movingSounds = this.soundGenerator.AddSynthSoundCollection(WorkingDirectory + \"movingBall2.music\");\t\n\t\t\n\t\tIFrequenceToneSnipped movingDownSound = movingSounds[0];\n\t\tIFrequenceToneSnipped movingUpSound = movingSounds[1];\n\t\t\n\t\tmovingDownSound.Play();             // First call from Play: start playback \n\t\t\n\t\tmovingDownSound.Play();\t\t\t\t// second call from Play: This will start the playback again from the beginning\n\t\t\n\t\t//... wait as long as you want \n\t\t\n\t\tmovingDownSound.Stop();\n\t}\n\t\n\tpublic void Dispose()\n\t{\n\t\tthis.soundGenerator.Dispose(); \t\t\t  // Destroy the AudioTimer inside from this object\n\t}\n}\n```\n\nIn the demoapplication a left-mouse-click creates a ball which is falling down. If you click multiple times then you can create multiple balls. In this case every ball has its own fallingdown-sound \nand we need for each a own IFrequenceToneSnipped-object, where the ball can control the playback from Play/Stop.\n\nIf you want to play the same sound multiple times then you need to use the GetCopy-method. This is needet, if you have multiple objects (in our example balls), which are creating the same sound \nbut each sound has his own start- and stop-time. You can call Play/Stop for each sound (ISoundSnipped-object) as often as you want. If your object, which is creating the sounds is destroyed, then its \nrecommended to Dispose the ISoundSnipped-object. Otherwise the SoundGenerator will hold a reference on this object and if you create with GetCopy many ISoundSnipped-objects, then the memory-usage \nwould become bigger with the time. \n\n```csharp\nvar movingSounds = this.soundGenerator.AddSynthSoundCollection(WorkingDirectory + \"movingBall2.music\");\t\n\t\t\nIFrequenceToneSnipped movingDownSound = movingSounds[0];\n\nvar movingDownSound1 = movingDownSound.GetCopy();\nvar movingDownSound2 = movingDownSound.GetCopy();\n\nmovingDownSound1.Play();              // Play is now used for movingDownSound1 and not for movingDownSound\nmovingDownSound2.Play(); \t\t\t  // call Play for \tmovingDownSound2. This will create a second playback for this sound.\n\n//... wait as long as you want \n\nmovingDownSound1.Stop();\nmovingDownSound2.Stop();\n\t\t\n//If you don't need the movingDownSound1-object anymore, then you should Dispose it\nmovingDownSound1.Dispose(); \n\n//the same for movingDownSound2\nmovingDownSound2.Dispose();\n\t\t\n}\n```\n\n## Case 3: play tones with a predefined length created by a oscillator-signal-source\n\n\n### Case 3 Step 1: Define the instrument and the tonelength in the MusicMachine-Editor to create a *.music-file\n\n\nIf the ball hits the ground, we want to play a drum-sound. This sound should be defined with the MusicMachine-Editor. So start the editor and create a new session and use the default-settings.\nThe sound should sound soft so we use a sinus-signal (1). We also want multiple signalsources so we increase the Count-Slider (4) and change the Pitch (5) a little bit. This will create a \nsinus-sound with choruseffect. The sound should decrease so we use the FreqRamp-Effect (2) and move the Ramp-Slider (3) a little bit down. The drum should play short so we set the attack-time (6)\nand the sustain-volume (8) to zero. The decaytime (7) defines the length from our sound. Since the sound is currently very quiet we are using the Gain-Effect (9) and move the gain-slider (10)\na little bit left.\n\n![Drum.jpg](https://raw.githubusercontent.com/XMAMan/SoundEngineExamples/refs/heads/main/Data/Images/Drum.jpg)\n\nWe now add a single note by left-clicking in the sequencer-note-area (11). You can move the right side from the rectangle(note) to the left or right to define the key-down-time. With this \nsingle note our *.music-file has now a predefined length and we don't need the stop-command durring using in the game. \n\nThis is our created music-file: [Drum.music](https://github.com/XMAMan/SoundEngineExamples/raw/refs/heads/main/Data/Drum.music)\n\n### Case 3 Step 2: Use the *.music-file in your game\n\n\nThe usage from the ground-hit-sound is similar to the usage from the background-music. Both examples uses a *.music-file as input. The difference is, that the background music contains multiple notes\nand sequencer and the hit-sound has only one sequencer with one note. We are using the GetCopy-method here because we want to create this song for each ball-object so the song can be played \nmultiple times. GetCopy creates a new instance from this song and saves it in the SoundGenerator. The hitSound should only played one time and after that we can remove the copy from the SoundGenerator\nby using the EndTrigger to register a handler, which is called after the song was played. We call in this handler \"hitSound.Dispose()\" to remove the hitSound-copy from the SoundGenerator.\n\n```csharp\nclass ViewModel : IDisposable\n{\n\tprivate SoundGenerator soundGenerator;\n\tprivate IMusicFileSnipped hitGroundSound;                       // This controls the sound when the ball hits the ground\n\t\n\tpublic ViewModel()\n\t{\n\t\tthis.soundGenerator = new SoundGenerator();\n\t\t\n\t\tthis.hitGroundSound = this.soundGenerator.AddMusicFile(WorkingDirectory + \"Drum.music\");\n\t\t\n\t\t//create a copy from the hitGroundSound-object and saves it in the SoundGenerator.\n\t\tISoundSnippedWithEndTrigger hitSound = this.hitGroundSound.GetCopy();\n\t\t\n\t\t\n\t\thitSound.EndTrigger += () =\u003e\n\t\t{\n\t\t\thitSound.Dispose(); //remove the hitSound-object in the SoundGenerator\n\t\t};\n\t\t\n\t\thitSound.Play(); //start playing the hitSound\n\n\t}\n\t\n\tpublic void Dispose()\n\t{\n\t\tthis.soundGenerator.Dispose(); \t\t\t  // Destroy the AudioTimer inside from this object\n\t}\n}\n```\n\n## Case 4: play a simple mp3/wma/wav-file\n\nTo play a mp3/wma/wav-file you only need to add it to the SoundGenerator with AddSoundFile and you can play it then with Play. If you want it to play mulitple times at the same time then use again \nthe GetCopy-function and call Play for every copy.\n\n```csharp\nclass ViewModel : IDisposable\n{\n\tprivate SoundGenerator soundGenerator;\n\tprivate IAudioFileSnipped hitCeilingSound;                      // This controls the sound when the ball hits the ceiling\n\t\n\tpublic ViewModel()\n\t{\n\t\tthis.soundGenerator = new SoundGenerator();\n\t\t\n\t\tthis.hitCeilingSound = this.soundGenerator.AddSoundFile(WorkingDirectory + \"427788__fullmetaljedi__metal-to-glass05-broke-it.wav\");\n\t\t\n\t\t//create a copy from the hitCeilingSound-object and saves it in the SoundGenerator.\n\t\tISoundSnippedWithEndTrigger hitSound = this.hitCeilingSound.GetCopy();\n\t\t\n\t\t\n\t\thitSound.EndTrigger += () =\u003e\n\t\t{\n\t\t\thitSound.Dispose(); //remove the hitSound-object in the SoundGenerator after playing it one time\n\t\t};\n\t\t\n\t\thitSound.Play(); //start playing the hitSound one time\n\n\t}\n\t\n\tpublic void Dispose()\n\t{\n\t\tthis.soundGenerator.Dispose(); \t\t\t  // Destroy the AudioTimer inside from this object\n\t}\n}\n```\n\nYou can also use a audiofile in the MusicMachine and create your own songs with it. For doing this add a empty sequencer and use AudioFile as audiosource (1). Click on the yellow rectangle (2) \nand select a mp3/wma/wav-file to open it. After that you can move the blue sliders (3) to define the start- and stop-time. You can change the pitch (4) and speed (5) from this audiofile. \nCreate now notes in the sequencer-area below. You can use the same audio-file multiple times by inserting multiple sequencers and define for each sequencer then your own values for pitch and \nspeed. \n\nThis could be a song only created with a single *.wav-file with three different pitches.\n\n![DrumSound.jpg](https://raw.githubusercontent.com/XMAMan/SoundEngineExamples/refs/heads/main/Data/Images/DrumSound.jpg)\n\nThis music file [DrumSound.music](https://github.com/XMAMan/SoundEngineExamples/raw/refs/heads/main/Data/DrumSound.music) creates this song: [DrumSound.mp3](https://github.com/XMAMan/SoundEngineExamples/raw/refs/heads/main/Data/SoundExamples/DrumSound.mp3)\n\n\n# Usecases if you want to create a audiorecorder\n\nFor this step: Open the AudioInput-project from here: https://github.com/XMAMan/SoundEngineExamples/tree/master/Source/SoundEngineExamples.sln\n\nIf you want to use a audioinput-device, then you have to use the AudioRecorder from the SoundGenerator-object. This will save the data from the microphone in the float-list 'recordData'. If you press\nthe StartStop-Button, then you can save the recorded data as mp3-file.\n\n```csharp\nclass ViewModel : IDisposable\n{\n\tprivate SoundGenerator soundGenerator = new SoundGenerator();                          // This comes from the XMAMan.SoundEngine-NuGet-Package\n\n\tprivate List\u003cfloat\u003e recordData = new List\u003cfloat\u003e();\t\t\t\t\t\t\t\t\t   //This saves our data from the microphone\n\tprivate bool isRecording = false;\n\n\tpublic ReactiveCommand\u003cUnit, Unit\u003e StartStopCommand { get; private set; }\n\n\t[Reactive] public double OutputVolume { get; set; } = 0;\t\t\t\t\t\t\t   //This property is used for showing the output volume\n\n\tpublic ViewModel()\n\t{\n\t\tthis.soundGenerator.AudioRecorder.StartRecording();\n\t\t\n\t\t//handler for the audio-output-timer\n\t\tthis.soundGenerator.AudioOutputCallback += (sender, buffer) =\u003e\n\t\t{\n\t\t\tif (this.isRecording)\n\t\t\t{\n\t\t\t\tthis.recordData.AddRange(buffer);\n\t\t\t}\n\n\t\t\tthis.OutputVolume = buffer.Sum(x =\u003e Math.Abs(x)) / buffer.Length;\n\t\t};\n\t\t\n\t\t//handler for the StartStop-Button\n\t\tthis.StartStopCommand = ReactiveCommand.CreateFromTask(async () =\u003e\n\t\t{\n\t\t\tif (this.isRecording)\n\t\t\t{\n\t\t\t\t//Stop recording and save recorded data into mp3-file.\n\t\t\t\tthis.isRecording = false;\n\t\t\t\tthis.soundGenerator.AudioFileWriter.ExportAudioStreamToFile(this.recordData.ToArray(), this.soundGenerator.SampleRate, \"output.mp3\");\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\t//Start recording and clear the recordData-buffer\n\t\t\t\tthis.isRecording = true;\n\t\t\t\tthis.recordData.Clear();\n\t\t\t}\n\t\t});\n\t}\n\n\n\tpublic void Dispose()\n\t{\n\t\tthis.soundGenerator.Dispose(); \t\t\t  // Destroy the AudioTimer inside from this object\n\t}\n}\n```\n\nAfter calling StartRecording, all audiodata from the selected audio-input-device is send to the current selected audio-output-device. To switch the current selected audio-device there are this functions:\n\n```csharp\nstring[] inputDevices = soundGenerator.AudioRecorder.GetAvailableDevices();\nsoundGenerator.AudioRecorder.SelectedDevice = inputDevices[0]; //here you select which input device to use.\n\nstring[] outputDevices = soundGenerator.GetAvailableOutputDevices();\nsoundGenerator.SelectedOutputDevice = outputDevices[0];\t//use outputdevice with index 0\n```\n\nThe sound, which comes from the microphone can be modified before sending it to the output device. To do this enable by example the hall-effect with this:\n\n```csharp\nsoundGenerator.AudioRecorder.UseHallEffect = true;\n```\n\n## You can use this demo-application for this cases:\n\n\n### Case 1: You have a telephone call and want to sound like a robot.\n\nYou need two headsets connected to you computer. Headset 1 is placed beside your computer and headset 2 is on your head. In the demoapplication use headset 1 for audiooutput and headset 2 for audioinput.\nGo the the soundsettings on you windows-system and use headset 1 as input-device for your stereomixer. In your telephone-app use stereomix as inputdevice and headset 2 as outputdevice. Activate the \nrobot-effect in the demoapplication from this example here and the other person from your call will hear your voice with the robot-effect.\n\n### Case 2: You want to here a video from youtube with hall/robot-effect\n\nYou need two headsets connected to you computer. Headset 1 is placed beside your computer and headset 2 is on your head. In the demoapplication use the stereomix as audioinput and headset 2 as audiooutput.\nIn the windows-soundsettings use headset 1 as default-outputdevice and the stereomix uses headset 1 as input-source. If you now play a video from youtube then headset 1 is used for output and the \nstereomixer will use this data as a virtual microphone. The demoapplication from here is using the unmodified audiosignal from youtube and will it modifie and play it on headset 2, which is located on \nyour head. You will hear the youtube-video with changed sound. \n\n### Case 3: You want to record your own voise\n\nSelect your headset/microphone-array as input-device and and use \"NoOutput\" as output-device. This is necessary otherwise you would hear your own voice about your speakers at the same time as you \nhear your voice from you mouth. That sounds confusing. Now you can press the record-button and speak. After pressing the button again you can save your audio data as mp3/wav-file.\n\n# Usecases if you want to create a audioplayer\n\nFor this step: Open the AudioPlayer-project from here: https://github.com/XMAMan/SoundEngineExamples/tree/master/Source/SoundEngineExamples.sln\n\nYou can create a audiplayer and visualize the audiodata by doing two steps. Step 1 is that call AddSoundFile which adds the audiodata from a file to the SoundGenerator-object. Then you have two options\nfor audio-data-visulisation. Option 1: Show the lowpass-signal with GetLowPassSignalImage. Option 2 is a spectrum analyzer.\n\nThe spectrum analyzer is the black area and the lowpass-signal the image blow:\n\n![AudioPlayer.jpg](https://raw.githubusercontent.com/XMAMan/SoundEngineExamples/refs/heads/main/Data/Images/AudioPlayer.jpg)\n\nIf you hear a low frequence signal, then the left side is changing and if you here a high frequence signal then the right side is changing in the spectrum analyzer. Use by example the \nbackground6.mp3-file to see this effect.\n\n```csharp\nclass ViewModel : IDisposable\n{\n\tprivate SoundGenerator soundGenerator = new SoundGenerator();                          // This comes from the XMAMan.SoundEngine-NuGet-Package\n\tprivate IAudioFileSnipped audioFile = null;\n\tprivate AudioFileAnalyser analyser = null;\n\n\t[Reactive] public BitmapImage SampleImage { get; set; }\t\t//Option 1 for visulisation: single image\n\t[Reactive] public float[] FrequencySpectrum { get; set; }\t//Option 2 for visulisation: spectrum analyzer\n\n\tpublic ViewModel()\n\t{\n\t\tthis.audioFile = soundGenerator.AddSoundFile(openFileDialog.FileName);\n\t\t\n\t\tthis.analyser = new AudioFileAnalyser(this.audioFile.AudioFileSamples, this.audioFile.SampleRate);\n\t\t\n\t\t//Option 1 for audio-visulisation: Create a image which shows the low-frequency-signal.\n\t\tthis.SampleImage = SignalImageCreator.GetLowPassSignalImage(analyser, this.ImageWidth, this.ImageHeight).ToBitmapImage();\n\t\t\n\t\t//Option 2 for visulisation: spectrum analyzer\n\t\tthis.timer = Observable.Interval(TimeSpan.FromMilliseconds(100))\n\t\t.Subscribe(x =\u003e\n\t\t{\n\t\t\t//Timer-Action\n\t\t\tif (this.audioFile != null \u0026\u0026 this.analyser != null)\n\t\t\t{\n\t\t\t\tdouble position = this.audioFile.SampleIndex / this.audioFile.SampleCount;\n\t\t\t\tthis.FrequencySpectrum = this.analyser.GetFrequenceSpectrumFromTime(position);\n\t\t\t}\n\t\t});\n\t}\n\t\n\tpublic void Dispose()\n\t{\n\t\tthis.soundGenerator.Dispose(); \t\t\t  // Destroy the AudioTimer inside from this object\n\t}\n}\n```\n\n```xml\nxmlns:controls=\"clr-namespace:AudioWpfControls.Controls;assembly=AudioWpfControls\"\n\n\u003ccontrols:SpectrumAnalyzer Values=\"{Binding FrequencySpectrum}\" Width=\"600\" Height=\"200\" /\u003e\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxmaman%2Fsoundengineexamples","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxmaman%2Fsoundengineexamples","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxmaman%2Fsoundengineexamples/lists"}