diff --git a/GstreamerHelper/GstreamerHelper.vcxproj b/GstreamerHelper/GstreamerHelper.vcxproj index cf79bf57..1c6e02b6 100644 --- a/GstreamerHelper/GstreamerHelper.vcxproj +++ b/GstreamerHelper/GstreamerHelper.vcxproj @@ -152,6 +152,7 @@ WIN32;_DEBUG;_WINDOWS;_USRDLL;GSTREAMERHELPER_EXPORTS;%(PreprocessorDefinitions) true Default + ProgramDatabase Windows diff --git a/Output/Languages/Czech.xml b/Output/Languages/Czech.xml index 918fe778..d4895f48 100644 --- a/Output/Languages/Czech.xml +++ b/Output/Languages/Czech.xml @@ -205,9 +205,9 @@ Pozadí obrazu Náhled obrazu Obrazové záznamy během přehrávání - Zobrazit nynější obrazový záznam k hudbě na pozadí - Kamery - Schopnosti kamer + Zobrazit nynější obrazový záznam k hudbě na pozadí + Kamery + Schopnosti kamer Přizpůsobení obrazovky Stiskněte Ctrl + Alt + Shift + šipky pro upravení obrazovky Ctrl + Alt + Shift + 0 pro vrácení úprav zpět na výchozí hodnoty diff --git a/Output/Languages/Dutch.xml b/Output/Languages/Dutch.xml index a50c8be9..8d959590 100644 --- a/Output/Languages/Dutch.xml +++ b/Output/Languages/Dutch.xml @@ -199,8 +199,8 @@ Videoachtergronden Videopreview Video tijdens zingen - Toon huidige achtergrondmuziekvideo - Webcams - Webcaminstellingen + Toon huidige achtergrondmuziekvideo + Webcams + Webcaminstellingen Volume diff --git a/Output/Languages/English.xml b/Output/Languages/English.xml index ea889529..b7360541 100644 --- a/Output/Languages/English.xml +++ b/Output/Languages/English.xml @@ -205,9 +205,9 @@ Video Backgrounds Video Preview Videos while singing - Display current backgroundmusic video - Webcams - Webcamcapabilities + Display current backgroundmusic video + Webcams + Webcam-Resolution Screen adjustments Press CTR + ALT + SHIFT + Arrows to adjust screen CTR + ALT + SHIFT + 0 to reset diff --git a/Output/Languages/French.xml b/Output/Languages/French.xml index ceab4219..5873c73b 100644 --- a/Output/Languages/French.xml +++ b/Output/Languages/French.xml @@ -205,9 +205,9 @@ Vidéo en arrière plan Prévisualisation des Vidéos Vidéos pendant que l\'on chante - Afficher la vidéo de la musique de fond - Webcams - Configuration Webcam + Afficher la vidéo de la musique de fond + Webcams + Configuration Webcam Ajustements de l\'écran Appuyer sur CTR + ALT + SHIFT + Flèches pour ajuster l\'écran CTR + ALT + SHIFT + 0 pour réinitialiser diff --git a/Output/Languages/German.xml b/Output/Languages/German.xml index 3025f8e1..52859778 100644 --- a/Output/Languages/German.xml +++ b/Output/Languages/German.xml @@ -206,9 +206,9 @@ Video-Hintergründe Video-Vorschau Videos während des Singens - Videos der Hintergrundmusik - Webcams - Webcamfähigkeiten + Videos der Hintergrundmusik + Webcams + Webcam-Auflösung Anzeigeanpassungen STRG + ALT + SHIFT + Pfeiltasten drücken um den Bildschirm anzupassen STRG + ALT + SHIFT + 0 um die Anpassungen zurückzusetzen diff --git a/Output/Languages/Hungarian.xml b/Output/Languages/Hungarian.xml index 2be6681a..3756f68e 100644 --- a/Output/Languages/Hungarian.xml +++ b/Output/Languages/Hungarian.xml @@ -190,8 +190,8 @@ Animált Háttér Videó Előnézet Videó Éneklés Közben - Jelenlegi Háttérzene Videó Mutatása - Webkamerák - Webkamera Tulajdonságok + Jelenlegi Háttérzene Videó Mutatása + Webkamerák + Webkamera Tulajdonságok Hangerő diff --git a/Output/Languages/Spanish.xml b/Output/Languages/Spanish.xml index 7e3b28c2..558e20bc 100644 --- a/Output/Languages/Spanish.xml +++ b/Output/Languages/Spanish.xml @@ -173,5 +173,5 @@ Videos de Fondo Previsualización del Video Videos al Cantar - TODO: Display current backgroundmusic video + TODO: Display current backgroundmusic video diff --git a/Output/Languages/Swedish.xml b/Output/Languages/Swedish.xml index 9d4068f9..aae0a1a7 100644 --- a/Output/Languages/Swedish.xml +++ b/Output/Languages/Swedish.xml @@ -205,9 +205,9 @@ Video Bakgrund Video Förhandsvisning Video Samtidigt Med Låt - Visa nuvarande Video för Bakgrundsmusik - Webkameror - Webkamera Kapacitet + Visa nuvarande Video för Bakgrundsmusik + Webkameror + Webkamera Kapacitet Skärmjusteringar Tryck CTRL + ALT +SHIFT + Pilar för att justera skärmen CTRL + ALT + SHIFT + 0 för att återställa diff --git a/Output/Languages/Turkish.xml b/Output/Languages/Turkish.xml index 6268cd7f..dff41110 100644 --- a/Output/Languages/Turkish.xml +++ b/Output/Languages/Turkish.xml @@ -190,8 +190,8 @@ Video Arka Planları Video Önizleme Şarkı Söylerken Videoları Gösterme - Mevcut Arka Plan Müziği Videosunu Göster - Web Kameraları - Web Kameraları Özellikleri + Mevcut Arka Plan Müziği Videosunu Göster + Web Kameraları + Web Kameraları Özellikleri Ses diff --git a/Output/LICENSE Newtonsoft.Json.txt b/Output/Licenses/Newtonsoft.Json/LICENSE.txt similarity index 100% rename from Output/LICENSE Newtonsoft.Json.txt rename to Output/Licenses/Newtonsoft.Json/LICENSE.txt diff --git a/Output/Licenses/Newtonsoft.Json/SourceAndVersion.txt b/Output/Licenses/Newtonsoft.Json/SourceAndVersion.txt new file mode 100644 index 00000000..a61fd5b6 --- /dev/null +++ b/Output/Licenses/Newtonsoft.Json/SourceAndVersion.txt @@ -0,0 +1,6 @@ +http://json.codeplex.com/ + +Version: Json.NET 6.0 Release 1 (.Net 4.0) + +Files: +Newtonsoft.Json.dll \ No newline at end of file diff --git a/Output/Newtonsoft.Json.dll b/Output/Newtonsoft.Json.dll index a1c39382..339e470c 100644 Binary files a/Output/Newtonsoft.Json.dll and b/Output/Newtonsoft.Json.dll differ diff --git a/Output/Themes/Ambient/Screens/ScreenNames.xml b/Output/Themes/Ambient/Screens/ScreenNames.xml index 4efddb2d..5d17ebe2 100644 --- a/Output/Themes/Ambient/Screens/ScreenNames.xml +++ b/Output/Themes/Ambient/Screens/ScreenNames.xml @@ -1155,8 +1155,8 @@ 8 2,00 - - + + TR_CONFIG_OFF @@ -1182,8 +1182,8 @@ 8 2,00 - - + + TR_CONFIG_OFF @@ -1209,8 +1209,8 @@ 8 2,00 - - + + TR_CONFIG_OFF @@ -1236,8 +1236,8 @@ 8 2,00 - - + + TR_CONFIG_OFF @@ -1263,8 +1263,8 @@ 8 2,00 - - + + TR_CONFIG_OFF @@ -1290,8 +1290,8 @@ 8 2,00 - - + + TR_CONFIG_OFF diff --git a/Output/Themes/Ambient/Screens/ScreenOptionsRecord.xml b/Output/Themes/Ambient/Screens/ScreenOptionsRecord.xml index ba0ce824..77c04934 100644 --- a/Output/Themes/Ambient/Screens/ScreenOptionsRecord.xml +++ b/Output/Themes/Ambient/Screens/ScreenOptionsRecord.xml @@ -782,11 +782,11 @@ 230 150 - 10 + 12 2,00 - - + + TR_CONFIG_OFF @@ -794,7 +794,7 @@ ButtonColor - ButtonColor + ButtonTextColor @@ -813,11 +813,11 @@ 230 150 - 10 + 12 2,00 - - + + TR_CONFIG_OFF @@ -825,7 +825,7 @@ ButtonColor - ButtonColor + ButtonTextColor diff --git a/Output/Themes/Ambient/Screens/ScreenOptionsVideo.xml b/Output/Themes/Ambient/Screens/ScreenOptionsVideo.xml index e7e928c0..cabb55d9 100644 --- a/Output/Themes/Ambient/Screens/ScreenOptionsVideo.xml +++ b/Output/Themes/Ambient/Screens/ScreenOptionsVideo.xml @@ -1,7 +1,7 @@  - 4 + 5 Video @@ -233,12 +233,12 @@ Outline - TR_SCREENO_VIDEO_VIDEOSTOBACKGROUND + TR_SCREENOVIDEO_VIDEOSTOBACKGROUND - + 75 347 @@ -262,12 +262,12 @@ Outline - TR_SCREENO_VIDEO_WEBCAMDEVICES + TR_SCREENOVIDEO_WEBCAMDEVICES - - + + 75 407 @@ -291,11 +291,11 @@ Outline - TR_SCREENO_VIDEO_WEBCAMCAPABILITIES + TR_SCREENOVIDEO_WEBCAMRESOLUTION - + Button diff --git a/Output/Themes/Changelog/Changelog_ScreenOptionsVideo.txt b/Output/Themes/Changelog/Changelog_ScreenOptionsVideo.txt index dea01208..9e8d37df 100644 --- a/Output/Themes/Changelog/Changelog_ScreenOptionsVideo.txt +++ b/Output/Themes/Changelog/Changelog_ScreenOptionsVideo.txt @@ -1,4 +1,8 @@ -ScreenOptionsTheme +++++++++++ +Version 5: + +Rename: +Text5/6 to TextWebcam/TextWebcamResolution ++++++++++ Version 4: diff --git a/PartyModes/PartyModeChallenge/PartyModeChallenge.csproj b/PartyModes/PartyModeChallenge/PartyModeChallenge.csproj index e9ca8fc6..193da7d0 100644 --- a/PartyModes/PartyModeChallenge/PartyModeChallenge.csproj +++ b/PartyModes/PartyModeChallenge/PartyModeChallenge.csproj @@ -1,8 +1,8 @@  - Debug - x86 + DebugWin + AnyCPU 8.0.30703 2.0 {5A4053F1-5AD5-441F-B254-D97A088127B6} @@ -14,29 +14,7 @@ Client 512 - - AnyCPU - true - full - false - bin - TRACE;DEBUG;WIN - prompt - 4 - Off - - - AnyCPU - none - true - bin - prompt - 4 - false - WIN - Off - - + AnyCPU true full @@ -48,7 +26,7 @@ Off ..\..\CheckingRules.ruleset - + AnyCPU none true @@ -59,7 +37,7 @@ WIN Off - + AnyCPU true full @@ -70,7 +48,7 @@ 4 Off - + AnyCPU none true @@ -81,42 +59,7 @@ LINUX Off - - AnyCPU - true - full - false - bin - TRACE;DEBUG;LINUX - prompt - 4 - Off - - - AnyCPU - none - true - bin - prompt - 4 - false - LINUX - Off - - - - - - bin - WIN - true - AnyCPU - false - Off - prompt - ManagedMinimumRules.ruleset - - + bin WIN true diff --git a/PartyModes/PartyModeChallengeMedley/PartyModeChallengeMedley.csproj b/PartyModes/PartyModeChallengeMedley/PartyModeChallengeMedley.csproj index 4f6ab862..135ffa4c 100644 --- a/PartyModes/PartyModeChallengeMedley/PartyModeChallengeMedley.csproj +++ b/PartyModes/PartyModeChallengeMedley/PartyModeChallengeMedley.csproj @@ -1,8 +1,8 @@  - Debug - x86 + DebugWin + AnyCPU 8.0.30703 2.0 {6F3E1874-F28A-40E9-AFBD-31934D593678} @@ -14,29 +14,7 @@ Client 512 - - AnyCPU - true - full - false - bin - TRACE;DEBUG;WIN - prompt - 4 - Off - - - AnyCPU - none - true - bin - prompt - 4 - false - WIN - Off - - + AnyCPU true full @@ -48,7 +26,7 @@ Off ..\..\CheckingRules.ruleset - + AnyCPU none true @@ -59,7 +37,7 @@ WIN Off - + AnyCPU true full @@ -70,7 +48,7 @@ 4 Off - + AnyCPU none true @@ -81,42 +59,7 @@ LINUX Off - - AnyCPU - true - full - false - bin - TRACE;DEBUG;LINUX - prompt - 4 - Off - - - AnyCPU - none - true - bin - prompt - 4 - false - LINUX - Off - - - - - - bin - WIN - true - AnyCPU - false - Off - prompt - ManagedMinimumRules.ruleset - - + bin WIN true diff --git a/PartyModes/PartyModeTicTacToe/PartyModeTicTacToe.csproj b/PartyModes/PartyModeTicTacToe/PartyModeTicTacToe.csproj index fb739e23..0ccffb7b 100644 --- a/PartyModes/PartyModeTicTacToe/PartyModeTicTacToe.csproj +++ b/PartyModes/PartyModeTicTacToe/PartyModeTicTacToe.csproj @@ -1,8 +1,8 @@  - Debug - x86 + DebugWin + AnyCPU 8.0.30703 2.0 {6F3E1874-F28A-40E9-AFBD-31934D593679} @@ -14,29 +14,7 @@ Client 512 - - AnyCPU - true - full - false - bin - TRACE;DEBUG;WIN - prompt - 4 - Off - - - AnyCPU - none - true - bin - prompt - 4 - false - WIN - Off - - + AnyCPU true full @@ -48,7 +26,7 @@ Off ..\..\CheckingRules.ruleset - + AnyCPU none true @@ -59,7 +37,7 @@ WIN Off - + AnyCPU true full @@ -70,7 +48,7 @@ 4 Off - + AnyCPU none true @@ -81,42 +59,7 @@ LINUX Off - - AnyCPU - true - full - false - bin - TRACE;DEBUG;LINUX - prompt - 4 - Off - - - AnyCPU - none - true - bin - prompt - 4 - false - LINUX - Off - - - - - - bin - WIN - true - AnyCPU - false - Off - prompt - ManagedMinimumRules.ruleset - - + bin WIN true diff --git a/PitchTracker/FFT/FFT.cpp b/PitchTracker/FFT/FFT.cpp new file mode 100644 index 00000000..39fdb52f --- /dev/null +++ b/PitchTracker/FFT/FFT.cpp @@ -0,0 +1,180 @@ +/********************************************************************** + + FFT.cpp + + Dominic Mazzoni + + September 2000 + +*******************************************************************//*! + +\file FFT.cpp +\brief Fast Fourier Transform routines. + + This file contains a few FFT routines, including a real-FFT + routine that is almost twice as fast as a normal complex FFT, + and a power spectrum routine when you know you don't care + about phase information. + + Some of this code was based on a free implementation of an FFT + by Don Cross, available on the web at: + + http://www.intersrv.com/~dcross/fft.html + + The basic algorithm for his code was based on Numerican Recipes + in Fortran. I optimized his code further by reducing array + accesses, caching the bit reversal table, and eliminating + float-to-double conversions, and I added the routines to + calculate a real FFT and a real power spectrum. + +*//*******************************************************************/ + +#include +#include +#include + +#include "FFT.h" + +#include "RealFFTf.h" + +void DeinitFFT() +{ + // Deallocate any unused RealFFTf tables + CleanupFFT(); +} + +/* + * Real Fast Fourier Transform + * + */ +void RealFFT(int NumSamples, float *RealIn, float *RealOut, float *ImagOut) +{ + // Remap to RealFFTf() function + int i; + HFFT hFFT = GetFFT(NumSamples); + float *pFFT = new float[NumSamples]; + // Copy the data into the processing buffer + for(i=0; iBitReversed[i] ]; + ImagOut[i]=pFFT[hFFT->BitReversed[i]+1]; + } + // Handle the (real-only) DC and Fs/2 bins + RealOut[0] = pFFT[0]; + RealOut[i] = pFFT[1]; + ImagOut[0] = ImagOut[i] = 0; + // Fill in the upper half using symmetry properties + for(i++ ; iBitReversed[i]]; + } + // Handle the (real-only) DC + Out[0] = pFFT[0]; + delete [] pFFT; + ReleaseFFT(hFFT); +} + +/* + * PowerSpectrum + * + * This function computes the same as RealFFT, above, but + * adds the squares of the real and imaginary part of each + * coefficient, extracting the power and throwing away the + * phase. + * + * For speed, it does not call RealFFT, but duplicates some + * of its code. + */ + +void PowerSpectrum(int NumSamples, float *In, float *Out) +{ + // Remap to RealFFTf() function + int i; + HFFT hFFT = GetFFT(NumSamples); + float *pFFT = new float[NumSamples]; + // Copy the data into the processing buffer + for(i=0; iBitReversed[i] ]*pFFT[hFFT->BitReversed[i] ]) + + (pFFT[hFFT->BitReversed[i]+1]*pFFT[hFFT->BitReversed[i]+1]); + } + // Handle the (real-only) DC and Fs/2 bins + Out[0] = pFFT[0]*pFFT[0]; + Out[i] = pFFT[1]*pFFT[1]; + delete [] pFFT; + ReleaseFFT(hFFT); +} \ No newline at end of file diff --git a/PitchTracker/FFT/FFT.h b/PitchTracker/FFT/FFT.h new file mode 100644 index 00000000..b8919e61 --- /dev/null +++ b/PitchTracker/FFT/FFT.h @@ -0,0 +1,65 @@ +/********************************************************************** + + FFT.h + + Dominic Mazzoni + + September 2000 + + This file contains a few FFT routines, including a real-FFT + routine that is almost twice as fast as a normal complex FFT, + and a power spectrum routine which is more convenient when + you know you don't care about phase information. It now also + contains a few basic windowing functions. + + Some of this code was based on a free implementation of an FFT + by Don Cross, available on the web at: + + http://www.intersrv.com/~dcross/fft.html + + The basic algorithm for his code was based on Numerical Recipes + in Fortran. I optimized his code further by reducing array + accesses, caching the bit reversal table, and eliminating + float-to-double conversions, and I added the routines to + calculate a real FFT and a real power spectrum. + + Note: all of these routines use single-precision floats. + I have found that in practice, floats work well until you + get above 8192 samples. If you need to do a larger FFT, + you need to use doubles. + +**********************************************************************/ + +/* + * This is the function you will use the most often. + * Given an array of floats, this will compute the power + * spectrum by doing a Real FFT and then computing the + * sum of the squares of the real and imaginary parts. + * Note that the output array is half the length of the + * input array, and that NumSamples must be a power of two. + */ + +void PowerSpectrum(int NumSamples, float *In, float *Out); + +/* + * Computes an FFT when the input data is real but you still + * want complex data as output. The output arrays are the + * same length as the input, but will be conjugate-symmetric + * NumSamples must be a power of two. + */ + +void RealFFT(int NumSamples, + float *RealIn, float *RealOut, float *ImagOut); + +/* + * Computes an Inverse FFT when the input data is conjugate symmetric + * so the output is purely real. NumSamples must be a power of + * two. + * Requires: EXPERIMENTAL_USE_REALFFTF + */ +void InverseRealFFT(int NumSamples, + float *RealIn, float *ImagIn, float *RealOut); + +void RealInverseRealFFT(int NumSamples, float *In, float *Out); + +void DeinitFFT(); diff --git a/PitchTracker/FFT/License.txt b/PitchTracker/FFT/License.txt new file mode 100644 index 00000000..c2e7eafa --- /dev/null +++ b/PitchTracker/FFT/License.txt @@ -0,0 +1,299 @@ +Code in this folder is based on Code from Audacity. +License of that code is below: + +------------------------------------------------------------------------ + +Note: Audacity is distributed under the terms of the GNU GPL. +This includes everything in the source code distribution +except code in the lib-src directory. Code in the lib-src +directory may be released under a different license +(which is GPL-compatible). For a summary, see the +README.txt file, and for specific details, see the license +information inside each subdirectory of lib-src. + +Documentation is distributed under the Creative Commons license. +Please see here for that: +http://creativecommons.org/licenses/by/3.0/legalcode + +The full text of the GNU GPL follows: + +GNU GENERAL PUBLIC LICENSE +Version 2, June 1991 + +Copyright (C) 1989, 1991 Free Software Foundation, Inc. +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + +Preamble + +The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + +When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + +To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + +For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + +We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + +Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + +Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and +modification follow. + +GNU GENERAL PUBLIC LICENSE +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + +1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + +2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + +a) You must cause the modified files to carry prominent notices +stating that you changed the files and the date of any change. + +b) You must cause any work that you distribute or publish, that in +whole or in part contains or is derived from the Program or any +part thereof, to be licensed as a whole at no charge to all third +parties under the terms of this License. + +c) If the modified program normally reads commands interactively +when run, you must cause it, when started running for such +interactive use in the most ordinary way, to print or display an +announcement including an appropriate copyright notice and a +notice that there is no warranty (or else, saying that you provide +a warranty) and that users may redistribute the program under +these conditions, and telling the user how to view a copy of this +License. (Exception: if the Program itself is interactive but +does not normally print such an announcement, your work based on +the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + +3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + +a) Accompany it with the complete corresponding machine-readable +source code, which must be distributed under the terms of Sections +1 and 2 above on a medium customarily used for software interchange; or, + +b) Accompany it with a written offer, valid for at least three +years, to give any third party, for a charge no more than your +cost of physically performing source distribution, a complete +machine-readable copy of the corresponding source code, to be +distributed under the terms of Sections 1 and 2 above on a medium +customarily used for software interchange; or, + +c) Accompany it with the information you received as to the offer +to distribute corresponding source code. (This alternative is +allowed only for noncommercial distribution and only if you +received the program in object code or executable form with such +an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + +4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + +5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + +7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + +8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + +9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + +10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + +NO WARRANTY + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + +12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/PitchTracker/FFT/RealFFTf.cpp b/PitchTracker/FFT/RealFFTf.cpp new file mode 100644 index 00000000..a18be257 --- /dev/null +++ b/PitchTracker/FFT/RealFFTf.cpp @@ -0,0 +1,388 @@ +/* +* Program: REALFFTF.C +* Author: Philip Van Baren +* Date: 2 September 1993 +* +* Description: These routines perform an FFT on real data to get a conjugate-symmetric +* output, and an inverse FFT on conjugate-symmetric input to get a real +* output sequence. +* +* This code is for floating point data. +* +* Modified 8/19/1998 by Philip Van Baren +* - made the InitializeFFT and EndFFT routines take a structure +* holding the length and pointers to the BitReversed and SinTable +* tables. +* Modified 5/23/2009 by Philip Van Baren +* - Added GetFFT and ReleaseFFT routines to retain common SinTable +* and BitReversed tables so they don't need to be reallocated +* and recomputed on every call. +* - Added Reorder* functions to undo the bit-reversal +* +* Copyright (C) 2009 Philip VanBaren +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include + +#include "RealFFTf.h" +#ifdef EXPERIMENTAL_EQ_SSE_THREADED +#include "RealFFTf48x.h" +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 /* pi */ +#endif + +/* +* Initialize the Sine table and Twiddle pointers (bit-reversed pointers) +* for the FFT routine. +*/ +HFFT InitializeFFT(int fftlen) +{ + int i; + int temp; + int mask; + HFFT h; + + if((h=(HFFT)malloc(sizeof(FFTParam)))==NULL) + { + fprintf(stderr,"Error allocating memory for FFT\n"); + exit(8); + } + /* + * FFT size is only half the number of data points + * The full FFT output can be reconstructed from this FFT's output. + * (This optimization can be made since the data is real.) + */ + h->Points = fftlen/2; + + if((h->SinTable=(fft_type *)malloc(2*h->Points*sizeof(fft_type)))==NULL) + { + fprintf(stderr,"Error allocating memory for Sine table.\n"); + exit(8); + } + + if((h->BitReversed=(int *)malloc(h->Points*sizeof(int)))==NULL) + { + fprintf(stderr,"Error allocating memory for BitReversed.\n"); + exit(8); + } + + for(i=0;iPoints;i++) + { + temp=0; + for(mask=h->Points/2;mask>0;mask >>= 1) + temp=(temp >> 1) + (i&mask ? h->Points : 0); + + h->BitReversed[i]=temp; + } + + for(i=0;iPoints;i++) + { + h->SinTable[h->BitReversed[i] ]=(fft_type)-sin(2*M_PI*i/(2*h->Points)); + h->SinTable[h->BitReversed[i]+1]=(fft_type)-cos(2*M_PI*i/(2*h->Points)); + } + + return h; +} + +/* +* Free up the memory allotted for Sin table and Twiddle Pointers +*/ +void EndFFT(HFFT h) +{ + if(h->Points>0) { + free(h->BitReversed); + free(h->SinTable); + } + h->Points=0; + free(h); +} + +#define MAX_HFFT 10 +static HFFT hFFTArray[MAX_HFFT] = { NULL }; +static int nFFTLockCount[MAX_HFFT] = { 0 }; + +/* Get a handle to the FFT tables of the desired length */ +/* This version keeps common tables rather than allocating a new table every time */ +HFFT GetFFT(int fftlen) +{ + int h,n = fftlen/2; + for(h=0; (hPoints); h++); + if(hBitReversed[i] ] +* Imag_i = buffer[ h->BitReversed[i]+1 ] ) +* Input is in normal order. +* +* Output buffer[0] is the DC bin, and output buffer[1] is the Fs/2 bin +* - this can be done because both values will always be real only +* - this allows us to not have to allocate an extra complex value for the Fs/2 bin +* +* Note: The scaling on this is done according to the standard FFT definition, +* so a unit amplitude DC signal will output an amplitude of (N) +* (Older revisions would progressively scale the input, so the output +* values would be similar in amplitude to the input values, which is +* good when using fixed point arithmetic) +*/ +void RealFFTf(fft_type *buffer,HFFT h) +{ + fft_type *A,*B; + fft_type *sptr; + fft_type *endptr1,*endptr2; + int *br1,*br2; + fft_type HRplus,HRminus,HIplus,HIminus; + fft_type v1,v2,sin,cos; + + int ButterfliesPerGroup=h->Points/2; + + /* + * Butterfly: + * Ain-----Aout + * \ / + * / \ + * Bin-----Bout + */ + + endptr1=buffer+h->Points*2; + + while(ButterfliesPerGroup>0) + { + A=buffer; + B=buffer+ButterfliesPerGroup*2; + sptr=h->SinTable; + + while(A>= 1; + } + /* Massage output to get the output for a real input sequence. */ + br1=h->BitReversed+1; + br2=h->BitReversed+h->Points-1; + + while(br1SinTable[*br1]; + cos=h->SinTable[*br1+1]; + A=buffer+*br1; + B=buffer+*br2; + HRplus = (HRminus = *A - *B ) + (*B * 2); + HIplus = (HIminus = *(A+1) - *(B+1)) + (*(B+1) * 2); + v1 = (sin*HRminus - cos*HIplus); + v2 = (cos*HRminus + sin*HIplus); + *A = (HRplus + v1) * (fft_type)0.5; + *B = *A - v1; + *(A+1) = (HIminus + v2) * (fft_type)0.5; + *(B+1) = *(A+1) - HIminus; + + br1++; + br2--; + } + /* Handle the center bin (just need a conjugate) */ + A=buffer+*br1+1; + *A=-*A; + /* Handle DC bin separately - and ignore the Fs/2 bin + buffer[0]+=buffer[1]; + buffer[1]=(fft_type)0;*/ + /* Handle DC and Fs/2 bins separately */ + /* Put the Fs/2 value into the imaginary part of the DC bin */ + v1=buffer[0]-buffer[1]; + buffer[0]+=buffer[1]; + buffer[1]=v1; +} + + +/* Description: This routine performs an inverse FFT to real data. +* This code is for floating point data. +* +* Note: Output is BIT-REVERSED! so you must use the BitReversed to +* get legible output, (i.e. wave[2*i] = buffer[ BitReversed[i] ] +* wave[2*i+1] = buffer[ BitReversed[i]+1 ] ) +* Input is in normal order, interleaved (real,imaginary) complex data +* You must call InitializeFFT(fftlen) first to initialize some buffers! +* +* Input buffer[0] is the DC bin, and input buffer[1] is the Fs/2 bin +* - this can be done because both values will always be real only +* - this allows us to not have to allocate an extra complex value for the Fs/2 bin +* +* Note: The scaling on this is done according to the standard FFT definition, +* so a unit amplitude DC signal will output an amplitude of (N) +* (Older revisions would progressively scale the input, so the output +* values would be similar in amplitude to the input values, which is +* good when using fixed point arithmetic) +*/ +void InverseRealFFTf(fft_type *buffer,HFFT h) +{ + fft_type *A,*B; + fft_type *sptr; + fft_type *endptr1,*endptr2; + int *br1; + fft_type HRplus,HRminus,HIplus,HIminus; + fft_type v1,v2,sin,cos; + + int ButterfliesPerGroup=h->Points/2; + + /* Massage input to get the input for a real output sequence. */ + A=buffer+2; + B=buffer+h->Points*2-2; + br1=h->BitReversed+1; + while(ASinTable[*br1]; + cos=h->SinTable[*br1+1]; + HRplus = (HRminus = *A - *B ) + (*B * 2); + HIplus = (HIminus = *(A+1) - *(B+1)) + (*(B+1) * 2); + v1 = (sin*HRminus + cos*HIplus); + v2 = (cos*HRminus - sin*HIplus); + *A = (HRplus + v1) * (fft_type)0.5; + *B = *A - v1; + *(A+1) = (HIminus - v2) * (fft_type)0.5; + *(B+1) = *(A+1) - HIminus; + + A+=2; + B-=2; + br1++; + } + /* Handle center bin (just need conjugate) */ + *(A+1)=-*(A+1); + /* Handle DC bin separately - this ignores any Fs/2 component + buffer[1]=buffer[0]=buffer[0]/2;*/ + /* Handle DC and Fs/2 bins specially */ + /* The DC bin is passed in as the real part of the DC complex value */ + /* The Fs/2 bin is passed in as the imaginary part of the DC complex value */ + /* (v1+v2) = buffer[0] == the DC component */ + /* (v1-v2) = buffer[1] == the Fs/2 component */ + v1=0.5f*(buffer[0]+buffer[1]); + v2=0.5f*(buffer[0]-buffer[1]); + buffer[0]=v1; + buffer[1]=v2; + + /* + * Butterfly: + * Ain-----Aout + * \ / + * / \ + * Bin-----Bout + */ + + endptr1=buffer+h->Points*2; + + while(ButterfliesPerGroup>0) + { + A=buffer; + B=buffer+ButterfliesPerGroup*2; + sptr=h->SinTable; + + while(A>= 1; + } +} + +void ReorderToFreq(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut) +{ + // Copy the data into the real and imaginary outputs + for(int i=1;iPoints;i++) { + RealOut[i]=buffer[hFFT->BitReversed[i] ]; + ImagOut[i]=buffer[hFFT->BitReversed[i]+1]; + } + RealOut[0] = buffer[0]; // DC component + ImagOut[0] = 0; + RealOut[hFFT->Points] = buffer[1]; // Fs/2 component + ImagOut[hFFT->Points] = 0; +} + +void ReorderToTime(HFFT hFFT, fft_type *buffer, fft_type *TimeOut) +{ + // Copy the data into the real outputs + for(int i=0;iPoints;i++) { + TimeOut[i*2 ]=buffer[hFFT->BitReversed[i] ]; + TimeOut[i*2+1]=buffer[hFFT->BitReversed[i]+1]; + } +} diff --git a/PitchTracker/FFT/RealFFTf.h b/PitchTracker/FFT/RealFFTf.h new file mode 100644 index 00000000..f46119ca --- /dev/null +++ b/PitchTracker/FFT/RealFFTf.h @@ -0,0 +1,23 @@ +#ifndef __realfftf_h +#define __realfftf_h + +#define fft_type float +typedef struct FFTParamType { + int *BitReversed; + fft_type *SinTable; + int Points; +} FFTParam; +#define HFFT FFTParam * + +HFFT InitializeFFT(int); +void EndFFT(HFFT); +HFFT GetFFT(int); +void ReleaseFFT(HFFT); +void CleanupFFT(); +void RealFFTf(fft_type *,HFFT); +void InverseRealFFTf(fft_type *,HFFT); +void ReorderToTime(HFFT hFFT, fft_type *buffer, fft_type *TimeOut); +void ReorderToFreq(HFFT hFFT, fft_type *buffer, fft_type *RealOut, fft_type *ImagOut); + +#endif + diff --git a/PitchTracker/PitchTracker.vcxproj b/PitchTracker/PitchTracker.vcxproj index 1b729255..65ce0ada 100644 --- a/PitchTracker/PitchTracker.vcxproj +++ b/PitchTracker/PitchTracker.vcxproj @@ -174,6 +174,8 @@ + + @@ -183,6 +185,8 @@ + + diff --git a/PitchTracker/PitchTracker.vcxproj.filters b/PitchTracker/PitchTracker.vcxproj.filters index 6e3d94f4..81447394 100644 --- a/PitchTracker/PitchTracker.vcxproj.filters +++ b/PitchTracker/PitchTracker.vcxproj.filters @@ -28,6 +28,12 @@ {2a09cee1-51b7-4c24-aa9f-32bec53c3a36} + + {498f64e2-ff83-41fd-be25-c613750f0e34} + + + {0791b62f-ef8d-40e2-b67e-a6d9dead8720} + @@ -51,6 +57,12 @@ Quelldateien + + Quelldateien\FFT + + + Quelldateien\FFT + @@ -77,6 +89,12 @@ Headerdateien\dywapitchtrack + + Headerdateien\FFT + + + Headerdateien\FFT + diff --git a/PitchTracker/performous/libda/sample.hpp b/PitchTracker/performous/libda/sample.hpp index a09bbcb6..da55bda7 100644 --- a/PitchTracker/performous/libda/sample.hpp +++ b/PitchTracker/performous/libda/sample.hpp @@ -1,7 +1,6 @@ #pragma once #include -#include "../compatibility.h" /** * @file sample.hpp Sample format definition and format conversions. diff --git a/PitchTracker/ptAKF.cpp b/PitchTracker/ptAKF.cpp index 335bcde6..27251d72 100644 --- a/PitchTracker/ptAKF.cpp +++ b/PitchTracker/ptAKF.cpp @@ -17,8 +17,13 @@ #include "ptAKF.h" #include +#ifdef USE_FFT +#include "FFT/FFT.h" +#endif + static constexpr double BaseToneFrequency = 65.4064; // lowest (half-)tone to analyze (C2 = 65.4064 Hz) static constexpr double HalftoneBase = 1.05946309436; // 2^(1/12) -> HalftoneBase^12 = 2 (one octave) + int PtAKF::_InitCount = 0; float* restrict PtAKF::_SamplesPerPeriodPerTone = NULL; float* restrict PtAKF::_SamplesPerPeriodPerToneFine = NULL; @@ -41,9 +46,9 @@ PtAKF::PtAKF(unsigned step){ _SamplesPerPeriodPerToneFine[2 * toneIndex + 1] = static_cast(44100.0 / GetFrequencyFromTone(toneIndex + 1./3.)); // samples for a bit above exact frequency } _Window = new float[_SampleCt]; - double cosMult = 2. * M_PI / (_SampleCt - 1.); //To simplify and speed up + double cosMult = 2. * M_PI / (2 * _SampleCt - 1.); //To simplify and speed up; 2 * _SampleCt because we extend the data by a factor of 2 for (int i = 0; i < _SampleCt; i++) { - _Window[i] = static_cast(0.64 - 0.36 * cos(i * cosMult)); + _Window[i] = static_cast(0.54 - 0.46 * cos(i * cosMult)); } } _Step = step; @@ -71,7 +76,6 @@ void PtAKF::SetVolumeThreshold(float threshold){ int PtAKF::GetNote(float* restrict maxVolume, float* restrict weights){ float AnaylsisBuf[_SampleCt]; int note = _LastTones[_LastToneIndex]; - *maxVolume = _LastMaxVol * 0.85f; if(_AnalysisBuf.read(AnaylsisBuf, AnaylsisBuf + _SampleCt)){ do{ _AnalysisBuf.pop(_Step); @@ -81,6 +85,9 @@ int PtAKF::GetNote(float* restrict maxVolume, float* restrict weights){ _LastTones[_LastToneIndex] = note; }while(_AnalysisBuf.read(AnaylsisBuf, AnaylsisBuf + _SampleCt)); note = _GetSmoothTone(); + _LastMaxVol = *maxVolume; + }else{ + *maxVolume = _LastMaxVol * 0.85f; } return note; } @@ -149,12 +156,20 @@ int PtAKF::_GetNote(float samples[_SampleCt], float* restrict maxVolume, float w if(maxVolumeL < _VolTreshold) return -1; - float samplesWindowed[_SampleCt]; + float samplesWindowed[_SampleCt * 2]; for(int i = 0; i < _SampleCt; i++){ samplesWindowed[i] = samples[i] * _Window[i]; } +#ifdef USE_FFT + for(int i = _SampleCt; i < _SampleCt * 2; i++){ + samplesWindowed[i] = 0.f; + } + float samplesFFT[_SampleCt+1]; // +1 for middle value! + PowerSpectrum(_SampleCt*2, samplesWindowed, samplesFFT); + RealInverseRealFFT(_SampleCt*2, samplesFFT, _AKFValues); +#endif // Now analyze the samples and get peaks at the most appropriate tones //Attention: We have a peak at lag 0 that might stretch that far, that we detect a wrong "peak" at _MaxHalfTone @@ -163,6 +178,7 @@ int PtAKF::_GetNote(float samples[_SampleCt], float* restrict maxVolume, float w float lastWeight = 1.f; float maxWeight = 0.f; + //TODO: When using FFT this can be speed up a lot by only checking around the AKF peaks #pragma omp parallel for schedule(static) for (int toneIndex = 0; toneIndex <= _MaxHalfTone; toneIndex++){ float curWeight = _AnalyzeByTone(samples, samplesWindowed, toneIndex); @@ -307,6 +323,10 @@ float PtAKF::_AKFBySampleCt(float samples[_SampleCt], float samplesPerPeriodD){ int samplesPerPeriod = static_cast(samplesPerPeriodD); float fHigh = samplesPerPeriodD - samplesPerPeriod; float fLow = 1.0f - fHigh; +#ifdef USE_FFT + float akf2 = _AKFValues[samplesPerPeriod] * fLow + _AKFValues[samplesPerPeriod+1] * fHigh; + return akf2 / (_SampleCt * _SampleCt); +#else float accumDist = 0; // accumulated distances @@ -322,10 +342,11 @@ float PtAKF::_AKFBySampleCt(float samples[_SampleCt], float samplesPerPeriodD){ } return accumDist / _SampleCt; +#endif } float PtAKF::_AMDFByTone(float samples[_SampleCt], int toneIndex){ - return _AKFBySampleCt(samples, _SamplesPerPeriodPerTone[toneIndex]); + return _AMDFBySampleCt(samples, _SamplesPerPeriodPerTone[toneIndex]); } float PtAKF::_AMDFBySampleCt(float samples[_SampleCt], float samplesPerPeriodD){ diff --git a/PitchTracker/ptAKF.h b/PitchTracker/ptAKF.h index b5d9a2b6..00f8aeb5 100644 --- a/PitchTracker/ptAKF.h +++ b/PitchTracker/ptAKF.h @@ -13,6 +13,8 @@ # endif #endif +#define USE_FFT + struct SPeak{ int toneIndex; float weight; @@ -55,14 +57,17 @@ private: float _LastMaxVol; int _LastTones[_SmoothCt]; int _LastToneIndex; +#ifdef USE_FFT + float _AKFValues[_SampleCt*2]; +#endif int _GetNote(float samples[_SampleCt], float* restrict maxVolume, float weights[_MaxHalfTone+1]); int _GetSmoothTone(); - static float _AnalyzeBySampleCt(float samples[_SampleCt], float samplesWindowed[_SampleCt], float samplesPerPeriodD); - static inline float _AnalyzeByTone(float samples[_SampleCt], float samplesWindowed[_SampleCt], int toneIndex); - static float _AKFBySampleCt(float samples[_SampleCt], float samplesPerPeriodD); - static inline float _AKFByTone(float samples[_SampleCt], int toneIndex); + float _AnalyzeBySampleCt(float samples[_SampleCt], float samplesWindowed[_SampleCt], float samplesPerPeriodD); + inline float _AnalyzeByTone(float samples[_SampleCt], float samplesWindowed[_SampleCt], int toneIndex); + float _AKFBySampleCt(float samples[_SampleCt], float samplesPerPeriodD); + inline float _AKFByTone(float samples[_SampleCt], int toneIndex); static float _AMDFBySampleCt(float samples[_SampleCt], float samplesPerPeriodD); static inline float _AMDFByTone(float samples[_SampleCt], int toneIndex); static inline void InitPeaks(SPeak peaks[_MaxPeaks]); diff --git a/Vocaluxe.sln b/Vocaluxe.sln index 0298c529..2ff35075 100644 --- a/Vocaluxe.sln +++ b/Vocaluxe.sln @@ -62,88 +62,89 @@ Global {2A1E0F2D-5392-4BB7-B0A1-A9DFA13E79FF}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 {2A1E0F2D-5392-4BB7-B0A1-A9DFA13E79FF}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 {2A1E0F2D-5392-4BB7-B0A1-A9DFA13E79FF}.ReleaseWin|x86.Build.0 = ReleaseWin|x86 - {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugLinux|x64.ActiveCfg = DebugLinux|x64 - {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugLinux|x64.Build.0 = DebugLinux|x64 - {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugLinux|x86.ActiveCfg = DebugLinux|x86 - {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugLinux|x86.Build.0 = DebugLinux|x86 - {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugWin|x64.ActiveCfg = DebugWin|x64 - {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugWin|x64.Build.0 = DebugWin|x64 - {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugWin|x86.ActiveCfg = DebugWin|x86 - {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugWin|x86.Build.0 = DebugWin|x86 - {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.InstallerWin|x64.ActiveCfg = InstallerWin|x64 - {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.InstallerWin|x64.Build.0 = InstallerWin|x64 - {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.InstallerWin|x86.ActiveCfg = InstallerWin|x86 - {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.InstallerWin|x86.Build.0 = InstallerWin|x86 - {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.ReleaseLinux|x64.ActiveCfg = ReleaseLinux|x64 - {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.ReleaseLinux|x64.Build.0 = ReleaseLinux|x64 - {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.ReleaseLinux|x86.ActiveCfg = ReleaseLinux|x86 - {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.ReleaseLinux|x86.Build.0 = ReleaseLinux|x86 - {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.ReleaseWin|x64.ActiveCfg = ReleaseWin|x64 - {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 - {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 - {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.ReleaseWin|x86.Build.0 = ReleaseWin|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593679}.DebugLinux|x64.ActiveCfg = DebugLinux|x64 - {6F3E1874-F28A-40E9-AFBD-31934D593679}.DebugLinux|x64.Build.0 = DebugLinux|x64 - {6F3E1874-F28A-40E9-AFBD-31934D593679}.DebugLinux|x86.ActiveCfg = DebugLinux|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593679}.DebugLinux|x86.Build.0 = DebugLinux|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593679}.DebugWin|x64.ActiveCfg = DebugWin|x64 - {6F3E1874-F28A-40E9-AFBD-31934D593679}.DebugWin|x64.Build.0 = DebugWin|x64 - {6F3E1874-F28A-40E9-AFBD-31934D593679}.DebugWin|x86.ActiveCfg = DebugWin|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593679}.DebugWin|x86.Build.0 = DebugWin|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593679}.InstallerWin|x64.ActiveCfg = InstallerWin|x64 - {6F3E1874-F28A-40E9-AFBD-31934D593679}.InstallerWin|x64.Build.0 = InstallerWin|x64 - {6F3E1874-F28A-40E9-AFBD-31934D593679}.InstallerWin|x86.ActiveCfg = InstallerWin|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593679}.InstallerWin|x86.Build.0 = InstallerWin|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593679}.ReleaseLinux|x64.ActiveCfg = ReleaseLinux|x64 - {6F3E1874-F28A-40E9-AFBD-31934D593679}.ReleaseLinux|x64.Build.0 = ReleaseLinux|x64 - {6F3E1874-F28A-40E9-AFBD-31934D593679}.ReleaseLinux|x86.ActiveCfg = ReleaseLinux|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593679}.ReleaseLinux|x86.Build.0 = ReleaseLinux|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593679}.ReleaseWin|x64.ActiveCfg = ReleaseWin|x64 - {6F3E1874-F28A-40E9-AFBD-31934D593679}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 - {6F3E1874-F28A-40E9-AFBD-31934D593679}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593679}.ReleaseWin|x86.Build.0 = ReleaseWin|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugLinux|x64.ActiveCfg = DebugLinux|x64 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugLinux|x64.Build.0 = DebugLinux|x64 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugLinux|x86.ActiveCfg = DebugLinux|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugLinux|x86.Build.0 = DebugLinux|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugWin|x64.ActiveCfg = DebugWin|x64 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugWin|x64.Build.0 = DebugWin|x64 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugWin|x86.ActiveCfg = DebugWin|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugWin|x86.Build.0 = DebugWin|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.InstallerWin|x64.ActiveCfg = ReleaseWin|x64 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.InstallerWin|x64.Build.0 = ReleaseWin|x64 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.InstallerWin|x86.ActiveCfg = ReleaseWin|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.InstallerWin|x86.Build.0 = ReleaseWin|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseLinux|x64.ActiveCfg = ReleaseLinux|x64 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseLinux|x64.Build.0 = ReleaseLinux|x64 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseLinux|x86.ActiveCfg = ReleaseLinux|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseLinux|x86.Build.0 = ReleaseLinux|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseWin|x64.ActiveCfg = ReleaseWin|x64 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 - {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseWin|x86.Build.0 = ReleaseWin|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugLinux|x64.ActiveCfg = DebugLinux|x64 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugLinux|x64.Build.0 = DebugLinux|x64 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugLinux|x86.ActiveCfg = DebugLinux|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugLinux|x86.Build.0 = DebugLinux|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugWin|x64.ActiveCfg = DebugWin|x64 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugWin|x64.Build.0 = DebugWin|x64 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugWin|x86.ActiveCfg = DebugWin|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugWin|x86.Build.0 = DebugWin|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.InstallerWin|x64.ActiveCfg = ReleaseWin|x64 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.InstallerWin|x64.Build.0 = ReleaseWin|x64 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.InstallerWin|x86.ActiveCfg = ReleaseWin|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.InstallerWin|x86.Build.0 = ReleaseWin|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseLinux|x64.ActiveCfg = ReleaseLinux|x64 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseLinux|x64.Build.0 = ReleaseLinux|x64 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseLinux|x86.ActiveCfg = ReleaseLinux|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseLinux|x86.Build.0 = ReleaseLinux|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseWin|x64.ActiveCfg = ReleaseWin|x64 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 - {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseWin|x86.Build.0 = ReleaseWin|x86 + {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugLinux|x64.ActiveCfg = DebugLinux|Any CPU + {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugLinux|x64.Build.0 = DebugLinux|Any CPU + {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugLinux|x86.ActiveCfg = DebugLinux|Any CPU + {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugLinux|x86.Build.0 = DebugLinux|Any CPU + {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugWin|x64.ActiveCfg = DebugWin|Any CPU + {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugWin|x64.Build.0 = DebugWin|Any CPU + {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugWin|x86.ActiveCfg = DebugWin|Any CPU + {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.DebugWin|x86.Build.0 = DebugWin|Any CPU + {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.InstallerWin|x64.ActiveCfg = InstallerWin|Any CPU + {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.InstallerWin|x64.Build.0 = InstallerWin|Any CPU + {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.InstallerWin|x86.ActiveCfg = InstallerWin|Any CPU + {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.InstallerWin|x86.Build.0 = InstallerWin|Any CPU + {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.ReleaseLinux|x64.ActiveCfg = ReleaseLinux|Any CPU + {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.ReleaseLinux|x64.Build.0 = ReleaseLinux|Any CPU + {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.ReleaseLinux|x86.ActiveCfg = ReleaseLinux|Any CPU + {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.ReleaseLinux|x86.Build.0 = ReleaseLinux|Any CPU + {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.ReleaseWin|x64.ActiveCfg = ReleaseWin|Any CPU + {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.ReleaseWin|x64.Build.0 = ReleaseWin|Any CPU + {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.ReleaseWin|x86.ActiveCfg = ReleaseWin|Any CPU + {D2B6DDEF-E0E1-4DDF-A73A-E6ACEF5C95EC}.ReleaseWin|x86.Build.0 = ReleaseWin|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593679}.DebugLinux|x64.ActiveCfg = DebugLinux|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593679}.DebugLinux|x64.Build.0 = DebugLinux|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593679}.DebugLinux|x86.ActiveCfg = DebugLinux|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593679}.DebugLinux|x86.Build.0 = DebugLinux|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593679}.DebugWin|x64.ActiveCfg = DebugWin|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593679}.DebugWin|x64.Build.0 = DebugWin|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593679}.DebugWin|x86.ActiveCfg = DebugWin|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593679}.DebugWin|x86.Build.0 = DebugWin|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593679}.InstallerWin|x64.ActiveCfg = InstallerWin|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593679}.InstallerWin|x64.Build.0 = InstallerWin|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593679}.InstallerWin|x86.ActiveCfg = InstallerWin|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593679}.InstallerWin|x86.Build.0 = InstallerWin|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593679}.ReleaseLinux|x64.ActiveCfg = ReleaseLinux|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593679}.ReleaseLinux|x64.Build.0 = ReleaseLinux|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593679}.ReleaseLinux|x86.ActiveCfg = ReleaseLinux|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593679}.ReleaseLinux|x86.Build.0 = ReleaseLinux|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593679}.ReleaseWin|x64.ActiveCfg = ReleaseWin|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593679}.ReleaseWin|x64.Build.0 = ReleaseWin|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593679}.ReleaseWin|x86.ActiveCfg = ReleaseWin|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593679}.ReleaseWin|x86.Build.0 = ReleaseWin|Any CPU + {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugLinux|x64.ActiveCfg = DebugLinux|Any CPU + {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugLinux|x64.Build.0 = DebugLinux|Any CPU + {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugLinux|x86.ActiveCfg = DebugLinux|Any CPU + {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugLinux|x86.Build.0 = DebugLinux|Any CPU + {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugWin|x64.ActiveCfg = DebugWin|Any CPU + {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugWin|x64.Build.0 = DebugWin|Any CPU + {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugWin|x86.ActiveCfg = DebugWin|Any CPU + {5A4053F1-5AD5-441F-B254-D97A088127B6}.DebugWin|x86.Build.0 = DebugWin|Any CPU + {5A4053F1-5AD5-441F-B254-D97A088127B6}.InstallerWin|x64.ActiveCfg = InstallerWin|Any CPU + {5A4053F1-5AD5-441F-B254-D97A088127B6}.InstallerWin|x64.Build.0 = InstallerWin|Any CPU + {5A4053F1-5AD5-441F-B254-D97A088127B6}.InstallerWin|x86.ActiveCfg = InstallerWin|Any CPU + {5A4053F1-5AD5-441F-B254-D97A088127B6}.InstallerWin|x86.Build.0 = InstallerWin|Any CPU + {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseLinux|x64.ActiveCfg = ReleaseLinux|Any CPU + {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseLinux|x64.Build.0 = ReleaseLinux|Any CPU + {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseLinux|x86.ActiveCfg = ReleaseLinux|Any CPU + {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseLinux|x86.Build.0 = ReleaseLinux|Any CPU + {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseWin|x64.ActiveCfg = ReleaseWin|Any CPU + {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseWin|x64.Build.0 = ReleaseWin|Any CPU + {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseWin|x86.ActiveCfg = ReleaseWin|Any CPU + {5A4053F1-5AD5-441F-B254-D97A088127B6}.ReleaseWin|x86.Build.0 = ReleaseWin|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugLinux|x64.ActiveCfg = DebugLinux|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugLinux|x64.Build.0 = DebugLinux|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugLinux|x86.ActiveCfg = DebugLinux|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugLinux|x86.Build.0 = DebugLinux|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugWin|x64.ActiveCfg = DebugWin|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugWin|x64.Build.0 = DebugWin|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugWin|x86.ActiveCfg = DebugWin|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593678}.DebugWin|x86.Build.0 = DebugWin|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593678}.InstallerWin|x64.ActiveCfg = InstallerWin|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593678}.InstallerWin|x64.Build.0 = InstallerWin|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593678}.InstallerWin|x86.ActiveCfg = InstallerWin|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593678}.InstallerWin|x86.Build.0 = InstallerWin|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseLinux|x64.ActiveCfg = ReleaseLinux|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseLinux|x64.Build.0 = ReleaseLinux|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseLinux|x86.ActiveCfg = ReleaseLinux|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseLinux|x86.Build.0 = ReleaseLinux|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseWin|x64.ActiveCfg = ReleaseWin|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseWin|x64.Build.0 = ReleaseWin|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseWin|x86.ActiveCfg = ReleaseWin|Any CPU + {6F3E1874-F28A-40E9-AFBD-31934D593678}.ReleaseWin|x86.Build.0 = ReleaseWin|Any CPU {ED007796-367F-4142-AA55-5450C7645C2C}.DebugLinux|x64.ActiveCfg = DebugWin|x64 - {ED007796-367F-4142-AA55-5450C7645C2C}.DebugLinux|x86.ActiveCfg = DebugWin|x64 + {ED007796-367F-4142-AA55-5450C7645C2C}.DebugLinux|x86.ActiveCfg = DebugWin|Win32 + {ED007796-367F-4142-AA55-5450C7645C2C}.DebugLinux|x86.Build.0 = DebugWin|Win32 {ED007796-367F-4142-AA55-5450C7645C2C}.DebugWin|x64.ActiveCfg = DebugWin|x64 {ED007796-367F-4142-AA55-5450C7645C2C}.DebugWin|x64.Build.0 = DebugWin|x64 {ED007796-367F-4142-AA55-5450C7645C2C}.DebugWin|x86.ActiveCfg = DebugWin|Win32 @@ -153,7 +154,7 @@ Global {ED007796-367F-4142-AA55-5450C7645C2C}.InstallerWin|x86.ActiveCfg = ReleaseWin|Win32 {ED007796-367F-4142-AA55-5450C7645C2C}.InstallerWin|x86.Build.0 = ReleaseWin|Win32 {ED007796-367F-4142-AA55-5450C7645C2C}.ReleaseLinux|x64.ActiveCfg = ReleaseWin|x64 - {ED007796-367F-4142-AA55-5450C7645C2C}.ReleaseLinux|x86.ActiveCfg = ReleaseWin|x64 + {ED007796-367F-4142-AA55-5450C7645C2C}.ReleaseLinux|x86.ActiveCfg = ReleaseWin|Win32 {ED007796-367F-4142-AA55-5450C7645C2C}.ReleaseWin|x64.ActiveCfg = ReleaseWin|x64 {ED007796-367F-4142-AA55-5450C7645C2C}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 {ED007796-367F-4142-AA55-5450C7645C2C}.ReleaseWin|x86.ActiveCfg = ReleaseWin|Win32 @@ -168,8 +169,8 @@ Global {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugWin|x86.Build.0 = DebugWin|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.InstallerWin|x64.ActiveCfg = ReleaseWin|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.InstallerWin|x64.Build.0 = ReleaseWin|Any CPU - {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.InstallerWin|x86.ActiveCfg = ReleaseLinux|Any CPU - {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.InstallerWin|x86.Build.0 = ReleaseLinux|Any CPU + {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.InstallerWin|x86.ActiveCfg = ReleaseWin|Any CPU + {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.InstallerWin|x86.Build.0 = ReleaseWin|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseLinux|x64.ActiveCfg = ReleaseLinux|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseLinux|x64.Build.0 = ReleaseLinux|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseLinux|x86.ActiveCfg = ReleaseLinux|Any CPU diff --git a/Vocaluxe.sln.DotSettings b/Vocaluxe.sln.DotSettings index 0a1c7cf8..661e1a2c 100644 --- a/Vocaluxe.sln.DotSettings +++ b/Vocaluxe.sln.DotSettings @@ -10,7 +10,7 @@ DO_NOT_SHOW DO_NOT_SHOW <?xml version="1.0" encoding="utf-16"?><Profile name="Cleanup"><CSArrangeThisQualifier>True</CSArrangeThisQualifier><CSRemoveCodeRedundancies>True</CSRemoveCodeRedundancies><CSUseVar><BehavourStyle>CAN_CHANGE_TO_EXPLICIT</BehavourStyle><LocalVariableStyle>IMPLICIT_WHEN_INITIALIZER_HAS_TYPE</LocalVariableStyle><ForeachVariableStyle>ALWAYS_EXPLICIT</ForeachVariableStyle></CSUseVar><CSOptimizeUsings><OptimizeUsings>False</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSReformatCode>True</CSReformatCode><CSharpFormatDocComments>True</CSharpFormatDocComments><CSShortenReferences>True</CSShortenReferences><StyleCop.Documentation><SA1600ElementsMustBeDocumented>False</SA1600ElementsMustBeDocumented><SA1604ElementDocumentationMustHaveSummary>False</SA1604ElementDocumentationMustHaveSummary><SA1609PropertyDocumentationMustHaveValueDocumented>False</SA1609PropertyDocumentationMustHaveValueDocumented><SA1611ElementParametersMustBeDocumented>False</SA1611ElementParametersMustBeDocumented><SA1615ElementReturnValueMustBeDocumented>False</SA1615ElementReturnValueMustBeDocumented><SA1617VoidReturnValueMustNotBeDocumented>False</SA1617VoidReturnValueMustNotBeDocumented><SA1618GenericTypeParametersMustBeDocumented>False</SA1618GenericTypeParametersMustBeDocumented><SA1626SingleLineCommentsMustNotUseDocumentationStyleSlashes>False</SA1626SingleLineCommentsMustNotUseDocumentationStyleSlashes><SA1628DocumentationTextMustBeginWithACapitalLetter>False</SA1628DocumentationTextMustBeginWithACapitalLetter><SA1629DocumentationTextMustEndWithAPeriod>False</SA1629DocumentationTextMustEndWithAPeriod><SA1633SA1641UpdateFileHeader>Ignore</SA1633SA1641UpdateFileHeader><SA1639FileHeaderMustHaveSummary>False</SA1639FileHeaderMustHaveSummary><SA1642ConstructorSummaryDocumentationMustBeginWithStandardText>False</SA1642ConstructorSummaryDocumentationMustBeginWithStandardText><SA1643DestructorSummaryDocumentationMustBeginWithStandardText>False</SA1643DestructorSummaryDocumentationMustBeginWithStandardText><SA1644DocumentationHeadersMustNotContainBlankLines>False</SA1644DocumentationHeadersMustNotContainBlankLines></StyleCop.Documentation><StyleCop.Layout><SA1500CurlyBracketsForMultiLineStatementsMustNotShareLine>False</SA1500CurlyBracketsForMultiLineStatementsMustNotShareLine><SA1509OpeningCurlyBracketsMustNotBePrecededByBlankLine>True</SA1509OpeningCurlyBracketsMustNotBePrecededByBlankLine><SA1510ChainedStatementBlocksMustNotBePrecededByBlankLine>True</SA1510ChainedStatementBlocksMustNotBePrecededByBlankLine><SA1511WhileDoFooterMustNotBePrecededByBlankLine>True</SA1511WhileDoFooterMustNotBePrecededByBlankLine><SA1512SingleLineCommentsMustNotBeFollowedByBlankLine>True</SA1512SingleLineCommentsMustNotBeFollowedByBlankLine><SA1513ClosingCurlyBracketMustBeFollowedByBlankLine>False</SA1513ClosingCurlyBracketMustBeFollowedByBlankLine><SA1514ElementDocumentationHeaderMustBePrecededByBlankLine>False</SA1514ElementDocumentationHeaderMustBePrecededByBlankLine><SA1515SingleLineCommentMustBeProceededByBlankLine>False</SA1515SingleLineCommentMustBeProceededByBlankLine></StyleCop.Layout><StyleCop.Readability><SA1100DoNotPrefixCallsWithBaseUnlessLocalImplementationExists>True</SA1100DoNotPrefixCallsWithBaseUnlessLocalImplementationExists><SA1106CodeMustNotContainEmptyStatements>True</SA1106CodeMustNotContainEmptyStatements><SA1108BlockStatementsMustNotContainEmbeddedComments>True</SA1108BlockStatementsMustNotContainEmbeddedComments><SA1109BlockStatementsMustNotContainEmbeddedRegions>True</SA1109BlockStatementsMustNotContainEmbeddedRegions><SA1120CommentsMustContainText>False</SA1120CommentsMustContainText><SA1121UseBuiltInTypeAlias>False</SA1121UseBuiltInTypeAlias><SA1122UseStringEmptyForEmptyStrings>False</SA1122UseStringEmptyForEmptyStrings><SA1123DoNotPlaceRegionsWithinElements>False</SA1123DoNotPlaceRegionsWithinElements><SA1124CodeMustNotContainEmptyRegions>True</SA1124CodeMustNotContainEmptyRegions></StyleCop.Readability><StyleCop.Spacing><SA1001CommasMustBeSpacedCorrectly>False</SA1001CommasMustBeSpacedCorrectly><SA1005SingleLineCommentsMustBeginWithSingleSpace>False</SA1005SingleLineCommentsMustBeginWithSingleSpace><SA1006PreprocessorKeywordsMustNotBePrecededBySpace>True</SA1006PreprocessorKeywordsMustNotBePrecededBySpace><SA1021NegativeSignsMustBeSpacedCorrectly>True</SA1021NegativeSignsMustBeSpacedCorrectly><SA1022PositiveSignsMustBeSpacedCorrectly>True</SA1022PositiveSignsMustBeSpacedCorrectly><SA1025CodeMustNotContainMultipleWhitespaceInARow>True</SA1025CodeMustNotContainMultipleWhitespaceInARow></StyleCop.Spacing><StyleCop.Ordering><AlphabeticalUsingDirectives>Ignore</AlphabeticalUsingDirectives><ExpandUsingDirectives>Ignore</ExpandUsingDirectives><SA1212PropertyAccessorsMustFollowOrder>True</SA1212PropertyAccessorsMustFollowOrder><SA1213EventAccessorsMustFollowOrder>True</SA1213EventAccessorsMustFollowOrder></StyleCop.Ordering><CSUpdateFileHeader>True</CSUpdateFileHeader><CSUseAutoProperty>True</CSUseAutoProperty></Profile> - <?xml version="1.0" encoding="utf-16"?><Profile name="Simple Reformat"><CSOptimizeUsings><OptimizeUsings>False</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSReformatCode>True</CSReformatCode><StyleCop.Documentation><SA1600ElementsMustBeDocumented>False</SA1600ElementsMustBeDocumented><SA1604ElementDocumentationMustHaveSummary>False</SA1604ElementDocumentationMustHaveSummary><SA1609PropertyDocumentationMustHaveValueDocumented>False</SA1609PropertyDocumentationMustHaveValueDocumented><SA1611ElementParametersMustBeDocumented>False</SA1611ElementParametersMustBeDocumented><SA1615ElementReturnValueMustBeDocumented>False</SA1615ElementReturnValueMustBeDocumented><SA1617VoidReturnValueMustNotBeDocumented>False</SA1617VoidReturnValueMustNotBeDocumented><SA1618GenericTypeParametersMustBeDocumented>False</SA1618GenericTypeParametersMustBeDocumented><SA1626SingleLineCommentsMustNotUseDocumentationStyleSlashes>False</SA1626SingleLineCommentsMustNotUseDocumentationStyleSlashes><SA1628DocumentationTextMustBeginWithACapitalLetter>False</SA1628DocumentationTextMustBeginWithACapitalLetter><SA1629DocumentationTextMustEndWithAPeriod>False</SA1629DocumentationTextMustEndWithAPeriod><SA1633SA1641UpdateFileHeader>Ignore</SA1633SA1641UpdateFileHeader><SA1639FileHeaderMustHaveSummary>False</SA1639FileHeaderMustHaveSummary><SA1642ConstructorSummaryDocumentationMustBeginWithStandardText>False</SA1642ConstructorSummaryDocumentationMustBeginWithStandardText><SA1643DestructorSummaryDocumentationMustBeginWithStandardText>False</SA1643DestructorSummaryDocumentationMustBeginWithStandardText><SA1644DocumentationHeadersMustNotContainBlankLines>False</SA1644DocumentationHeadersMustNotContainBlankLines></StyleCop.Documentation><StyleCop.Spacing><SA1001CommasMustBeSpacedCorrectly>False</SA1001CommasMustBeSpacedCorrectly><SA1005SingleLineCommentsMustBeginWithSingleSpace>False</SA1005SingleLineCommentsMustBeginWithSingleSpace><SA1006PreprocessorKeywordsMustNotBePrecededBySpace>True</SA1006PreprocessorKeywordsMustNotBePrecededBySpace><SA1021NegativeSignsMustBeSpacedCorrectly>True</SA1021NegativeSignsMustBeSpacedCorrectly><SA1022PositiveSignsMustBeSpacedCorrectly>True</SA1022PositiveSignsMustBeSpacedCorrectly><SA1025CodeMustNotContainMultipleWhitespaceInARow>True</SA1025CodeMustNotContainMultipleWhitespaceInARow></StyleCop.Spacing><StyleCop.Readability><SA1100DoNotPrefixCallsWithBaseUnlessLocalImplementationExists>True</SA1100DoNotPrefixCallsWithBaseUnlessLocalImplementationExists><SA1106CodeMustNotContainEmptyStatements>True</SA1106CodeMustNotContainEmptyStatements><SA1108BlockStatementsMustNotContainEmbeddedComments>True</SA1108BlockStatementsMustNotContainEmbeddedComments><SA1109BlockStatementsMustNotContainEmbeddedRegions>True</SA1109BlockStatementsMustNotContainEmbeddedRegions><SA1120CommentsMustContainText>False</SA1120CommentsMustContainText><SA1121UseBuiltInTypeAlias>False</SA1121UseBuiltInTypeAlias><SA1122UseStringEmptyForEmptyStrings>False</SA1122UseStringEmptyForEmptyStrings><SA1123DoNotPlaceRegionsWithinElements>False</SA1123DoNotPlaceRegionsWithinElements><SA1124CodeMustNotContainEmptyRegions>True</SA1124CodeMustNotContainEmptyRegions></StyleCop.Readability><StyleCop.Layout><SA1500CurlyBracketsForMultiLineStatementsMustNotShareLine>False</SA1500CurlyBracketsForMultiLineStatementsMustNotShareLine><SA1509OpeningCurlyBracketsMustNotBePrecededByBlankLine>True</SA1509OpeningCurlyBracketsMustNotBePrecededByBlankLine><SA1510ChainedStatementBlocksMustNotBePrecededByBlankLine>True</SA1510ChainedStatementBlocksMustNotBePrecededByBlankLine><SA1511WhileDoFooterMustNotBePrecededByBlankLine>True</SA1511WhileDoFooterMustNotBePrecededByBlankLine><SA1512SingleLineCommentsMustNotBeFollowedByBlankLine>True</SA1512SingleLineCommentsMustNotBeFollowedByBlankLine><SA1513ClosingCurlyBracketMustBeFollowedByBlankLine>False</SA1513ClosingCurlyBracketMustBeFollowedByBlankLine><SA1514ElementDocumentationHeaderMustBePrecededByBlankLine>False</SA1514ElementDocumentationHeaderMustBePrecededByBlankLine><SA1515SingleLineCommentMustBeProceededByBlankLine>False</SA1515SingleLineCommentMustBeProceededByBlankLine></StyleCop.Layout><StyleCop.Ordering><AlphabeticalUsingDirectives>Ignore</AlphabeticalUsingDirectives><ExpandUsingDirectives>Ignore</ExpandUsingDirectives><SA1212PropertyAccessorsMustFollowOrder>True</SA1212PropertyAccessorsMustFollowOrder><SA1213EventAccessorsMustFollowOrder>True</SA1213EventAccessorsMustFollowOrder></StyleCop.Ordering><CSShortenReferences>True</CSShortenReferences><CSUseVar><BehavourStyle>CAN_CHANGE_TO_EXPLICIT</BehavourStyle><LocalVariableStyle>IMPLICIT_WHEN_INITIALIZER_HAS_TYPE</LocalVariableStyle><ForeachVariableStyle>ALWAYS_EXPLICIT</ForeachVariableStyle></CSUseVar></Profile> + <?xml version="1.0" encoding="utf-16"?><Profile name="Simple Reformat"><CSOptimizeUsings><OptimizeUsings>False</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSReformatCode>True</CSReformatCode><StyleCop.Documentation><SA1600ElementsMustBeDocumented>False</SA1600ElementsMustBeDocumented><SA1604ElementDocumentationMustHaveSummary>False</SA1604ElementDocumentationMustHaveSummary><SA1609PropertyDocumentationMustHaveValueDocumented>False</SA1609PropertyDocumentationMustHaveValueDocumented><SA1611ElementParametersMustBeDocumented>False</SA1611ElementParametersMustBeDocumented><SA1615ElementReturnValueMustBeDocumented>False</SA1615ElementReturnValueMustBeDocumented><SA1617VoidReturnValueMustNotBeDocumented>False</SA1617VoidReturnValueMustNotBeDocumented><SA1618GenericTypeParametersMustBeDocumented>False</SA1618GenericTypeParametersMustBeDocumented><SA1626SingleLineCommentsMustNotUseDocumentationStyleSlashes>False</SA1626SingleLineCommentsMustNotUseDocumentationStyleSlashes><SA1628DocumentationTextMustBeginWithACapitalLetter>False</SA1628DocumentationTextMustBeginWithACapitalLetter><SA1629DocumentationTextMustEndWithAPeriod>False</SA1629DocumentationTextMustEndWithAPeriod><SA1633SA1641UpdateFileHeader>Ignore</SA1633SA1641UpdateFileHeader><SA1639FileHeaderMustHaveSummary>False</SA1639FileHeaderMustHaveSummary><SA1642ConstructorSummaryDocumentationMustBeginWithStandardText>False</SA1642ConstructorSummaryDocumentationMustBeginWithStandardText><SA1643DestructorSummaryDocumentationMustBeginWithStandardText>False</SA1643DestructorSummaryDocumentationMustBeginWithStandardText><SA1644DocumentationHeadersMustNotContainBlankLines>False</SA1644DocumentationHeadersMustNotContainBlankLines></StyleCop.Documentation><StyleCop.Spacing><SA1001CommasMustBeSpacedCorrectly>False</SA1001CommasMustBeSpacedCorrectly><SA1005SingleLineCommentsMustBeginWithSingleSpace>False</SA1005SingleLineCommentsMustBeginWithSingleSpace><SA1006PreprocessorKeywordsMustNotBePrecededBySpace>True</SA1006PreprocessorKeywordsMustNotBePrecededBySpace><SA1021NegativeSignsMustBeSpacedCorrectly>True</SA1021NegativeSignsMustBeSpacedCorrectly><SA1022PositiveSignsMustBeSpacedCorrectly>True</SA1022PositiveSignsMustBeSpacedCorrectly><SA1025CodeMustNotContainMultipleWhitespaceInARow>True</SA1025CodeMustNotContainMultipleWhitespaceInARow></StyleCop.Spacing><StyleCop.Readability><SA1100DoNotPrefixCallsWithBaseUnlessLocalImplementationExists>True</SA1100DoNotPrefixCallsWithBaseUnlessLocalImplementationExists><SA1106CodeMustNotContainEmptyStatements>True</SA1106CodeMustNotContainEmptyStatements><SA1108BlockStatementsMustNotContainEmbeddedComments>True</SA1108BlockStatementsMustNotContainEmbeddedComments><SA1109BlockStatementsMustNotContainEmbeddedRegions>True</SA1109BlockStatementsMustNotContainEmbeddedRegions><SA1120CommentsMustContainText>False</SA1120CommentsMustContainText><SA1121UseBuiltInTypeAlias>False</SA1121UseBuiltInTypeAlias><SA1122UseStringEmptyForEmptyStrings>False</SA1122UseStringEmptyForEmptyStrings><SA1123DoNotPlaceRegionsWithinElements>False</SA1123DoNotPlaceRegionsWithinElements><SA1124CodeMustNotContainEmptyRegions>True</SA1124CodeMustNotContainEmptyRegions></StyleCop.Readability><StyleCop.Layout><SA1500CurlyBracketsForMultiLineStatementsMustNotShareLine>False</SA1500CurlyBracketsForMultiLineStatementsMustNotShareLine><SA1509OpeningCurlyBracketsMustNotBePrecededByBlankLine>True</SA1509OpeningCurlyBracketsMustNotBePrecededByBlankLine><SA1510ChainedStatementBlocksMustNotBePrecededByBlankLine>True</SA1510ChainedStatementBlocksMustNotBePrecededByBlankLine><SA1511WhileDoFooterMustNotBePrecededByBlankLine>True</SA1511WhileDoFooterMustNotBePrecededByBlankLine><SA1512SingleLineCommentsMustNotBeFollowedByBlankLine>True</SA1512SingleLineCommentsMustNotBeFollowedByBlankLine><SA1513ClosingCurlyBracketMustBeFollowedByBlankLine>False</SA1513ClosingCurlyBracketMustBeFollowedByBlankLine><SA1514ElementDocumentationHeaderMustBePrecededByBlankLine>False</SA1514ElementDocumentationHeaderMustBePrecededByBlankLine><SA1515SingleLineCommentMustBeProceededByBlankLine>False</SA1515SingleLineCommentMustBeProceededByBlankLine></StyleCop.Layout><StyleCop.Ordering><AlphabeticalUsingDirectives>Ignore</AlphabeticalUsingDirectives><ExpandUsingDirectives>Ignore</ExpandUsingDirectives><SA1212PropertyAccessorsMustFollowOrder>True</SA1212PropertyAccessorsMustFollowOrder><SA1213EventAccessorsMustFollowOrder>True</SA1213EventAccessorsMustFollowOrder></StyleCop.Ordering><CSShortenReferences>True</CSShortenReferences><CSUseVar><BehavourStyle>CAN_CHANGE_TO_EXPLICIT</BehavourStyle><LocalVariableStyle>IMPLICIT_WHEN_INITIALIZER_HAS_TYPE</LocalVariableStyle><ForeachVariableStyle>ALWAYS_EXPLICIT</ForeachVariableStyle></CSUseVar><CSharpFormatDocComments>True</CSharpFormatDocComments></Profile> Cleanup Simple Reformat 0 diff --git a/Vocaluxe/Base/CBackgroundMusic.cs b/Vocaluxe/Base/CBackgroundMusic.cs index c06c0b2c..09bddfcc 100644 --- a/Vocaluxe/Base/CBackgroundMusic.cs +++ b/Vocaluxe/Base/CBackgroundMusic.cs @@ -128,8 +128,8 @@ namespace Vocaluxe.Base } /// - /// Initializes the background music with values from config - /// Has to be called before any other method is used + /// Initializes the background music with values from config + /// Has to be called before any other method is used /// public static void Init() { @@ -320,7 +320,7 @@ namespace Vocaluxe.Base } /// - /// (Re-)Starts the _CurrentPlaylistElement + /// (Re-)Starts the _CurrentPlaylistElement /// private static void _StartSong() { diff --git a/Vocaluxe/Base/CConfig.cs b/Vocaluxe/Base/CConfig.cs index 6eb0be6b..6b6d7bf0 100644 --- a/Vocaluxe/Base/CConfig.cs +++ b/Vocaluxe/Base/CConfig.cs @@ -106,7 +106,7 @@ namespace Vocaluxe.Base public static int GameMusicVolume = 80; //Folders - public static readonly List SongFolders = new List() + public static readonly List SongFolders = new List { Path.Combine(Directory.GetCurrentDirectory(), _FolderSongs) @@ -115,8 +115,8 @@ namespace Vocaluxe.Base #endif }; /// - /// Folders with profiles - /// First one is used for new profiles + /// Folders with profiles + /// First one is used for new profiles /// public static readonly List ProfileFolders = new List { diff --git a/Vocaluxe/Base/CCover.cs b/Vocaluxe/Base/CCover.cs index fddf06d2..5b52371b 100644 --- a/Vocaluxe/Base/CCover.cs +++ b/Vocaluxe/Base/CCover.cs @@ -214,8 +214,8 @@ namespace Vocaluxe.Base } /// - /// Ads a cover with the given name if it does not exist yet - /// MUST HOLD _Covers lock at this point + /// Ads a cover with the given name if it does not exist yet + /// MUST HOLD _Covers lock at this point /// /// Name of the cover /// Filename of image file diff --git a/Vocaluxe/Base/CDataBase.cs b/Vocaluxe/Base/CDataBase.cs index 3a512891..7721f663 100644 --- a/Vocaluxe/Base/CDataBase.cs +++ b/Vocaluxe/Base/CDataBase.cs @@ -29,6 +29,7 @@ using VocaluxeLib.Draw; using VocaluxeLib.Songs; #if WIN using System.Data.SQLite; + #else using Mono.Data.Sqlite; using SQLiteConnection = Mono.Data.Sqlite.SqliteConnection; @@ -1181,7 +1182,7 @@ namespace Vocaluxe.Base } /// - /// You have to hold the CoverMutex when calling this! + /// You have to hold the CoverMutex when calling this! /// private static void _CommitCovers() { diff --git a/Vocaluxe/Base/CParty.cs b/Vocaluxe/Base/CParty.cs index a52c0c60..2fd180c1 100644 --- a/Vocaluxe/Base/CParty.cs +++ b/Vocaluxe/Base/CParty.cs @@ -223,8 +223,8 @@ namespace Vocaluxe.Base foreach (string file in files) { SPartyMode pm = _LoadPartyMode(file); - if(pm.NoErrors) - _PartyModes.Add(pm.PartyModeID, pm); + if (pm.NoErrors) + _PartyModes.Add(pm.PartyModeID, pm); } } diff --git a/Vocaluxe/Base/CPlaylistElement.cs b/Vocaluxe/Base/CPlaylistElement.cs index 195be8e7..3b6588de 100644 --- a/Vocaluxe/Base/CPlaylistElement.cs +++ b/Vocaluxe/Base/CPlaylistElement.cs @@ -1,4 +1,21 @@ -using System; +#region license +// This file is part of Vocaluxe. +// +// Vocaluxe is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Vocaluxe is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Vocaluxe. If not, see . +#endregion + +using System; using VocaluxeLib.Draw; using VocaluxeLib.Songs; diff --git a/Vocaluxe/Base/CRecord.cs b/Vocaluxe/Base/CRecord.cs index 5af44fd1..43c8f099 100644 --- a/Vocaluxe/Base/CRecord.cs +++ b/Vocaluxe/Base/CRecord.cs @@ -1,4 +1,21 @@ -using System.Collections.ObjectModel; +#region license +// This file is part of Vocaluxe. +// +// Vocaluxe is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Vocaluxe is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Vocaluxe. If not, see . +#endregion + +using System.Collections.ObjectModel; using Vocaluxe.Lib.Sound.Record; using Vocaluxe.Lib.Sound.Record.DirectSound; using Vocaluxe.Lib.Sound.Record.PortAudio; @@ -79,6 +96,16 @@ namespace Vocaluxe.Base return _Record.GetMaxVolume(player); } + public static float GetVolumeThreshold(int player) + { + return _Record.GetVolumeThreshold(player); + } + + public static void SetVolumeThreshold(int player, float threshold) + { + _Record.SetVolumeThreshold(player, threshold); + } + public static int NumHalfTones(int player) { return _Record.NumHalfTones(); diff --git a/Vocaluxe/Base/CSettings.cs b/Vocaluxe/Base/CSettings.cs index 7c57abf1..3de72e98 100644 --- a/Vocaluxe/Base/CSettings.cs +++ b/Vocaluxe/Base/CSettings.cs @@ -34,8 +34,8 @@ namespace Vocaluxe.Base } /// - /// This class contains settings for the program - /// These are not editable, everything that can be changed by the user is in CConfig + /// This class contains settings for the program + /// These are not editable, everything that can be changed by the user is in CConfig /// static class CSettings { diff --git a/Vocaluxe/Base/CSongCategorizer.cs b/Vocaluxe/Base/CSongCategorizer.cs index 8c68e615..282e62a7 100644 --- a/Vocaluxe/Base/CSongCategorizer.cs +++ b/Vocaluxe/Base/CSongCategorizer.cs @@ -91,7 +91,7 @@ namespace Vocaluxe.Base } /// - /// Sets the SortStrings of the songpointers to the actual category names + /// Sets the SortStrings of the songpointers to the actual category names /// private static void _AdjustCategoryNames() { diff --git a/Vocaluxe/Base/CSound.cs b/Vocaluxe/Base/CSound.cs index a09ba20a..d5fbd50d 100644 --- a/Vocaluxe/Base/CSound.cs +++ b/Vocaluxe/Base/CSound.cs @@ -83,7 +83,8 @@ namespace Vocaluxe.Base public static void Close() { - CloseAllStreams(); + if (_Playback != null) + _Playback.Close(); _Playback = null; } diff --git a/Vocaluxe/Base/CWebcam.cs b/Vocaluxe/Base/CWebcam.cs index 0b7dcb46..af66025a 100644 --- a/Vocaluxe/Base/CWebcam.cs +++ b/Vocaluxe/Base/CWebcam.cs @@ -49,58 +49,70 @@ namespace Vocaluxe.Base return true; } + public static void Close() + { + if (_Webcam == null) + return; + _Webcam.Close(); + _Webcam = null; + } + public static bool GetFrame(ref CTexture tex) { - return _Webcam.GetFrame(ref tex); + return _Webcam != null && _Webcam.GetFrame(ref tex); } public static Bitmap GetBitmap() { - return _Webcam.GetBitmap(); - } - - public static void Close() - { - if (_Webcam != null) - { - _Webcam.Close(); - _Webcam = null; - } + return _Webcam == null ? null : _Webcam.GetBitmap(); } public static void Pause() { + if (_Webcam == null) + return; _Webcam.Pause(); } public static void Start() { + if (_Webcam == null) + return; _Webcam.Start(); } public static void Stop() { + if (_Webcam == null) + return; _Webcam.Stop(); } - public static void Select(SWebcamConfig c) + public static bool Select(SWebcamConfig c) { - _Webcam.Select(c); + return _Webcam != null && _Webcam.Select(c); + } + + public static void DeSelect() + { + if (_Webcam == null) + return; + _Webcam.DeSelect(); } public static SWebcamDevice[] GetDevices() { - return _Webcam.GetDevices(); + return _Webcam == null ? null : _Webcam.GetDevices(); } public static bool IsDeviceAvailable() { - return _Webcam.IsDeviceAvailable(); + return (_Webcam != null) && _Webcam.IsDeviceAvailable(); } public static bool IsCapturing() { - return _Webcam.IsCapturing(); + return (_Webcam != null) && _Webcam.IsCapturing(); } } } \ No newline at end of file diff --git a/Vocaluxe/Base/Server/CVocaluxeServer.cs b/Vocaluxe/Base/Server/CVocaluxeServer.cs index 19f91e62..c25462d0 100644 --- a/Vocaluxe/Base/Server/CVocaluxeServer.cs +++ b/Vocaluxe/Base/Server/CVocaluxeServer.cs @@ -318,8 +318,8 @@ namespace Vocaluxe.Base.Server { string filename = _SaveImage(avatarData, "snapshot", CConfig.ProfileFolders[0]); - var avatar = CAvatar.GetAvatar(filename); - if (avatar!=null) + CAvatar avatar = CAvatar.GetAvatar(filename); + if (avatar != null) { CProfiles.AddAvatar(avatar); return avatar; diff --git a/Vocaluxe/COSFunctions.cs b/Vocaluxe/COSFunctions.cs index 472956c6..d8aec79a 100644 --- a/Vocaluxe/COSFunctions.cs +++ b/Vocaluxe/COSFunctions.cs @@ -1,4 +1,21 @@ -using System; +#region license +// This file is part of Vocaluxe. +// +// Vocaluxe is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Vocaluxe is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Vocaluxe. If not, see . +#endregion + +using System; using System.Runtime.InteropServices; namespace Vocaluxe @@ -22,7 +39,7 @@ namespace Vocaluxe [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetForegroundWindow(IntPtr hWnd); - [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)] + [DllImport("kernel32.dll", CallingConvention = CallingConvention.StdCall)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool SetDefaultDllDirectories(int directoryFlags); diff --git a/Vocaluxe/Lib/Sound/CPortAudioHandle.cs b/Vocaluxe/Lib/Sound/CPortAudioHandle.cs index 0406055e..217afafa 100644 --- a/Vocaluxe/Lib/Sound/CPortAudioHandle.cs +++ b/Vocaluxe/Lib/Sound/CPortAudioHandle.cs @@ -1,4 +1,21 @@ -using System; +#region license +// This file is part of Vocaluxe. +// +// Vocaluxe is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Vocaluxe is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Vocaluxe. If not, see . +#endregion + +using System; using System.Collections.Generic; using System.Diagnostics; using PortAudioSharp; @@ -7,12 +24,11 @@ using Vocaluxe.Base; namespace Vocaluxe.Lib.Sound { /// - /// PortAudio can be used for record and playback - /// So do some common stuff here and make sure those 2 do not interfere - /// Basic lifetime: On Init() get a new handle, close/dispose it in your close/dispose - /// - /// DO NEVER use following Pa_* functions other than the ones from this class: - /// Initialize, Terminate, OpenStream, CloseStream + /// PortAudio can be used for record and playback + /// So do some common stuff here and make sure those 2 do not interfere + /// Basic lifetime: On Init() get a new handle, close/dispose it in your close/dispose + /// DO NEVER use following Pa_* functions other than the ones from this class: + /// Initialize, Terminate, OpenStream, CloseStream /// class CPortAudioHandle : IDisposable { @@ -23,7 +39,7 @@ namespace Vocaluxe.Lib.Sound private readonly List _Streams = new List(); /// - /// Initializes PortAudio library (if required) + /// Initializes PortAudio library (if required) /// public CPortAudioHandle() { @@ -73,7 +89,7 @@ namespace Vocaluxe.Lib.Sound } /// - /// Close the PortAudio handle once you are done + /// Close the PortAudio handle once you are done /// public void Close() { @@ -98,7 +114,7 @@ namespace Vocaluxe.Lib.Sound } /// - /// Convenience method to safely open an input stream and log potential error + /// Convenience method to safely open an input stream and log potential error /// /// /// @@ -119,7 +135,7 @@ namespace Vocaluxe.Lib.Sound } /// - /// Convenience method to safely open an output stream and log potential error + /// Convenience method to safely open an output stream and log potential error /// /// /// @@ -152,8 +168,8 @@ namespace Vocaluxe.Lib.Sound } /// - /// Checks if PA returned an error and logs it - /// Returns true on error + /// Checks if PA returned an error and logs it + /// Returns true on error /// /// Action identifier (E.g. openStream) /// Result returned by Pa_* call @@ -180,7 +196,7 @@ namespace Vocaluxe.Lib.Sound } /// - /// Selects the most appropriate host api + /// Selects the most appropriate host api /// /// The most appropriate host api public int GetHostApi() diff --git a/Vocaluxe/Lib/Sound/Playback/CRingBuffer.cs b/Vocaluxe/Lib/Sound/Playback/CRingBuffer.cs new file mode 100644 index 00000000..73d0ebe3 --- /dev/null +++ b/Vocaluxe/Lib/Sound/Playback/CRingBuffer.cs @@ -0,0 +1,79 @@ +using System; + +namespace Vocaluxe.Lib.Sound.Playback +{ + class CRingBuffer + { + private readonly byte[] _Data; + private readonly int _Size; + private int _ReadPos; + private int _WritePos; + private int _BytesNotRead; + + public int BytesNotRead + { + get { return _BytesNotRead; } + } + + public CRingBuffer(int size) + { + _Size = size; + _Data = new byte[size]; + Reset(); + } + + public void Reset() + { + _ReadPos = 0; + _WritePos = 0; + _BytesNotRead = 0; + } + + public void Write(byte[] data) + { + int start = 0; + int end = data.Length; + if (end - start > _Size) + start = end - _Size; + int lenTotal = end - start; + int len = Math.Min(lenTotal, _Size - _WritePos); + Buffer.BlockCopy(data, start, _Data, _WritePos, len); + _WritePos += len; + if (_WritePos >= _Size) + { + _WritePos = 0; + start += len; + len = end - start; + if (len > 0) + { + Buffer.BlockCopy(data, start, _Data, _WritePos, len); + _WritePos += len; + } + } + _BytesNotRead += lenTotal; + } + + public void Read(byte[] data) + { + int lenTotal = Math.Min(data.Length, _BytesNotRead); + if (lenTotal == 0) + return; + + int len = Math.Min(lenTotal, _Size - _ReadPos); + Buffer.BlockCopy(_Data, _ReadPos, data, 0, len); + _ReadPos += len; + if (_ReadPos >= _Size) + { + _ReadPos = 0; + int start = len; + len = lenTotal - len; + if (len > 0) + { + Buffer.BlockCopy(_Data, _ReadPos, data, start, len); + _ReadPos += len; + } + } + _BytesNotRead -= lenTotal; + } + } +} \ No newline at end of file diff --git a/Vocaluxe/Lib/Sound/Playback/Gstreamer/CGstreamerAudio.cs b/Vocaluxe/Lib/Sound/Playback/Gstreamer/CGstreamerAudio.cs index 66a30301..2b6a663a 100644 --- a/Vocaluxe/Lib/Sound/Playback/Gstreamer/CGstreamerAudio.cs +++ b/Vocaluxe/Lib/Sound/Playback/Gstreamer/CGstreamerAudio.cs @@ -45,6 +45,11 @@ namespace Vocaluxe.Lib.Sound.Playback.Gstreamer return CGstreamerAudioWrapper.Init(); } + public void Close() + { + CloseAll(); + } + public void SetGlobalVolume(float volume) { CGstreamerAudioWrapper.SetGlobalVolume(volume); diff --git a/Vocaluxe/Lib/Sound/Playback/GstreamerSharp/CGstreamerSharpAudio.cs b/Vocaluxe/Lib/Sound/Playback/GstreamerSharp/CGstreamerSharpAudio.cs index 640b0c8d..f95c2c91 100644 --- a/Vocaluxe/Lib/Sound/Playback/GstreamerSharp/CGstreamerSharpAudio.cs +++ b/Vocaluxe/Lib/Sound/Playback/GstreamerSharp/CGstreamerSharpAudio.cs @@ -27,6 +27,8 @@ namespace Vocaluxe.Lib.Sound.Playback.GstreamerSharp public bool Init() { + if (Application.IsInitialized) + return false; #if ARCH_X86 const string path = ".\\x86\\gstreamer"; #endif @@ -41,6 +43,14 @@ namespace Vocaluxe.Lib.Sound.Playback.GstreamerSharp return Application.IsInitialized; } + public void Close() + { + if (!Application.IsInitialized) + return; + CloseAll(); + Application.Deinit(); + } + public void SetGlobalVolume(float volume) { foreach (CGstreamerSharpAudioStream stream in _Streams.Values) diff --git a/Vocaluxe/Lib/Sound/Playback/GstreamerSharp/CGstreamerSharpAudioStream.cs b/Vocaluxe/Lib/Sound/Playback/GstreamerSharp/CGstreamerSharpAudioStream.cs index bbcbd725..c566c9b0 100644 --- a/Vocaluxe/Lib/Sound/Playback/GstreamerSharp/CGstreamerSharpAudioStream.cs +++ b/Vocaluxe/Lib/Sound/Playback/GstreamerSharp/CGstreamerSharpAudioStream.cs @@ -1,3 +1,20 @@ +#region license +// This file is part of Vocaluxe. +// +// Vocaluxe is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Vocaluxe is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Vocaluxe. If not, see . +#endregion + using System; using GLib; using Gst; diff --git a/Vocaluxe/Lib/Sound/Playback/IPlayback.cs b/Vocaluxe/Lib/Sound/Playback/IPlayback.cs index 13ce9857..b4a13057 100644 --- a/Vocaluxe/Lib/Sound/Playback/IPlayback.cs +++ b/Vocaluxe/Lib/Sound/Playback/IPlayback.cs @@ -40,6 +40,7 @@ namespace Vocaluxe.Lib.Sound.Playback interface IPlayback { bool Init(); + void Close(); void SetGlobalVolume(float volume); int GetStreamCount(); void CloseAll(); @@ -72,57 +73,4 @@ namespace Vocaluxe.Lib.Sound.Playback void Update(); #endregion Stream Handling } - - class CRingBuffer - { - private readonly byte[] _Data; - private readonly long _Size; - private long _ReadPos; - private long _WritePos; - private long _BytesNotRead; - - public long BytesNotRead - { - get { return _BytesNotRead; } - } - - public CRingBuffer(long size) - { - _Size = size; - _Data = new byte[size]; - _ReadPos = 0L; - _WritePos = 0L; - _BytesNotRead = 0L; - } - - public void Write(byte[] data) - { - long written = 0L; - while (written < data.Length) - { - _Data[_WritePos] = data[written]; - _WritePos++; - if (_WritePos >= _Size) - _WritePos = 0L; - - written++; - _BytesNotRead++; - } - } - - public void Read(byte[] data) - { - long read = 0L; - while (read < data.Length && _BytesNotRead > 0L) - { - data[read] = _Data[_ReadPos]; - _ReadPos++; - if (_ReadPos >= _Size) - _ReadPos = 0L; - - read++; - _BytesNotRead--; - } - } - } } \ No newline at end of file diff --git a/Vocaluxe/Lib/Sound/Playback/OpenAL/COpenALPlay.cs b/Vocaluxe/Lib/Sound/Playback/OpenAL/COpenALPlay.cs index ac7b533b..558ab7ee 100644 --- a/Vocaluxe/Lib/Sound/Playback/OpenAL/COpenALPlay.cs +++ b/Vocaluxe/Lib/Sound/Playback/OpenAL/COpenALPlay.cs @@ -16,6 +16,7 @@ #endregion using System.Linq; +using System.Threading; using OpenTK.Audio; using System; using System.Collections.Generic; @@ -34,10 +35,15 @@ namespace Vocaluxe.Lib.Sound.Playback.OpenAL private List _Streams; + ~COpenALPlay() + { + _Dispose(false); + } + public bool Init() { if (_Initialized) - CloseAll(); + return false; _Context = new AudioContext(); @@ -51,6 +57,11 @@ namespace Vocaluxe.Lib.Sound.Playback.OpenAL return true; } + public void Close() + { + Dispose(); + } + public void CloseAll() { lock (_MutexDecoder) @@ -321,24 +332,37 @@ namespace Vocaluxe.Lib.Sound.Playback.OpenAL private void _CloseProc(int streamID) { - if (_Initialized) + if (!_Initialized) + return; + lock (_MutexDecoder) { - lock (_MutexDecoder) + if (_AlreadyAdded(streamID)) { - if (_AlreadyAdded(streamID)) - { - int index = _GetStreamIndex(streamID); - _Decoder.RemoveAt(index); - _Streams.RemoveAt(index); - } + int index = _GetStreamIndex(streamID); + _Decoder.RemoveAt(index); + _Streams.RemoveAt(index); } } } public void Dispose() { - _Context.Dispose(); - _Context = null; + _Dispose(true); + } + + private void _Dispose(bool disposing) + { + CloseAll(); + if (disposing) + { + while (_Decoder.Count > 0) + Thread.Sleep(5); + } + if (_Context != null) + { + _Context.Dispose(); + _Context = null; + } } public void FadeAndStop(int stream, float targetVolume, float seconds) diff --git a/Vocaluxe/Lib/Sound/Playback/OpenAL/COpenAlStream.cs b/Vocaluxe/Lib/Sound/Playback/OpenAL/COpenAlStream.cs index f3742b7d..ec5bdefa 100644 --- a/Vocaluxe/Lib/Sound/Playback/OpenAL/COpenAlStream.cs +++ b/Vocaluxe/Lib/Sound/Playback/OpenAL/COpenAlStream.cs @@ -1,4 +1,21 @@ -using System; +#region license +// This file is part of Vocaluxe. +// +// Vocaluxe is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Vocaluxe is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Vocaluxe. If not, see . +#endregion + +using System; using System.Diagnostics; using System.IO; using System.Threading; @@ -9,11 +26,11 @@ using VocaluxeLib; namespace Vocaluxe.Lib.Sound.Playback.OpenAL { - class COpenAlStream : IDisposable + class COpenAlStream { private const int _BufferSize = 2048; private const int _BufferCount = 5; - private const long _Bufsize = 50000L; + private const int _Bufsize = 50000; private Object _CloseMutex; @@ -70,6 +87,7 @@ namespace Vocaluxe.Lib.Sound.Playback.OpenAL _StreamID = streamID; _Terminated = true; _CloseMutex = closeMutex; + _EventDecode.Set(); } public float Length @@ -270,7 +288,7 @@ namespace Vocaluxe.Lib.Sound.Playback.OpenAL lock (_MutexData) { - _Data = new CRingBuffer(_Bufsize); + _Data.Reset(); _NoMoreData = false; } } @@ -372,6 +390,11 @@ namespace Vocaluxe.Lib.Sound.Playback.OpenAL } _Closeproc(_StreamID); + if (_EventDecode != null) + { + _EventDecode.Dispose(); + _EventDecode = null; + } } #endregion Threading @@ -464,11 +487,5 @@ namespace Vocaluxe.Lib.Sound.Playback.OpenAL _CurrentTime = _TimeCode - _Data.BytesNotRead / _BytesPerSecond - 0.1f; _Timer.Restart(); } - - public void Dispose() - { - _EventDecode.Close(); - _EventDecode = null; - } } } \ No newline at end of file diff --git a/Vocaluxe/Lib/Sound/Playback/PortAudio/CPortAudioPlay.cs b/Vocaluxe/Lib/Sound/Playback/PortAudio/CPortAudioPlay.cs index 86f62f4d..96e6d3d7 100644 --- a/Vocaluxe/Lib/Sound/Playback/PortAudio/CPortAudioPlay.cs +++ b/Vocaluxe/Lib/Sound/Playback/PortAudio/CPortAudioPlay.cs @@ -21,29 +21,43 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio { class CPortAudioPlay : IPlayback { - private bool _Initialized; + private volatile bool _Initialized; private readonly List _Streams = new List(); private int _NextID; public bool Init() { if (_Initialized) - CloseAll(); + return false; _Initialized = true; return true; } + public void Close() + { + _Initialized = false; //Set this first, so threads don't call closeproc anymore + List streams = new List(); + //Get all streams but do not modify list without holding the lock + //Calling dispose from within the lock may deadlock in closeproc (if a thread is already there) + lock (_Streams) + { + streams.AddRange(_Streams); + _Streams.Clear(); + } + foreach (CPortAudioStream stream in streams) + stream.Dispose(); + } + public void CloseAll() { lock (_Streams) { foreach (CPortAudioStream stream in _Streams) - stream.Free(); + stream.Close(); _Streams.Clear(); } - _Initialized = false; } public void SetGlobalVolume(float volume) @@ -99,7 +113,7 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio int index = _GetStreamIndex(stream); if (index >= 0) { - _Streams[index].Free(); + _Streams[index].Close(); _Streams.RemoveAt(index); } } @@ -287,8 +301,8 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio #endregion Stream Handling /// - /// Returns true if strem with given id is found - /// MUST hold _Stream-lock + /// Returns true if strem with given id is found + /// MUST hold _Stream-lock /// /// Stream id /// @@ -298,8 +312,8 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio } /// - /// Returns the index of the stream with the given id - /// MUST hold _Stream-lock + /// Returns the index of the stream with the given id + /// MUST hold _Stream-lock /// /// Stream id /// @@ -314,7 +328,7 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio } /// - /// Removes the stream with the given handle + /// Removes the stream with the given handle /// /// Stream handle private void _CloseProc(int stream) diff --git a/Vocaluxe/Lib/Sound/Playback/PortAudio/CPortAudioStream.cs b/Vocaluxe/Lib/Sound/Playback/PortAudio/CPortAudioStream.cs index cd2328e2..1042e0f8 100644 --- a/Vocaluxe/Lib/Sound/Playback/PortAudio/CPortAudioStream.cs +++ b/Vocaluxe/Lib/Sound/Playback/PortAudio/CPortAudioStream.cs @@ -1,4 +1,21 @@ -using System; +#region license +// This file is part of Vocaluxe. +// +// Vocaluxe is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Vocaluxe is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Vocaluxe. If not, see . +#endregion + +using System; using System.IO; using System.Runtime.InteropServices; using System.Threading; @@ -10,8 +27,8 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio { class CPortAudioStream : IDisposable { - private const long _Bufsize = 1000000L; - private const long _Beginrefill = 800000L; + private const int _Bufsize = 1000000; + private const int _Beginrefill = 800000; public readonly int ID; private readonly Closeproc _Closeproc; @@ -36,22 +53,21 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio private bool _FileOpened; - private bool _Waiting; private bool _Skip; private bool _Loop; private float _Duration; private float _CurrentTime; - private float _TimeCode; + private volatile float _TimeCode; - private bool _Paused; + private volatile bool _Paused; private CRingBuffer _Data; - private float _SetStart; + private volatile float _SetStart; private float _Start; - private bool _SetLoop; - private bool _SetSkip; - private bool _Terminated; + private volatile bool _SetLoop; + private volatile bool _SetSkip; + private volatile bool _Terminated; private Thread _DecoderThread; @@ -69,12 +85,15 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio ~CPortAudioStream() { - Dispose(); + _Dispose(false); + if (_DecoderThread != null) + _DecoderThread.Join(); } - public void Free() + public void Close() { _Terminated = true; + _EventDecode.Set(); } public float Length @@ -94,7 +113,7 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio { lock (_LockData) { - return _NoMoreData && _Data.BytesNotRead == 0L && _SyncTimer.Time >= _Duration; + return _NoMoreData && _Data.BytesNotRead == 0 && _SyncTimer.Time >= _Duration; } } } @@ -104,11 +123,8 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio get { return _Volume * 100f; } set { - lock (_LockData) - { - value.Clamp(0f, 100f); - _Volume = value / 100f; - } + value.Clamp(0f, 100f); + _Volume = value / 100f; } } @@ -117,11 +133,8 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio get { return _VolumeMax * 100f; } set { - lock (_LockData) - { - value.Clamp(0f, 100f); - _VolumeMax = value / 100f; - } + value.Clamp(0f, 100f); + _VolumeMax = value / 100f; } } @@ -133,8 +146,7 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio { if (Finished) _SyncTimer.Pause(); - //TODO: Why not use Decoder.GetPosition()? - //Decoder may return wrong timestamps. If you change this to exessive testing for monoton timestamps espacially for ogg files + //Decoder may return wrong timestamps. If you change this do exessive testing for monoton timestamps espacially for ogg files return _SyncTimer.Time; } } @@ -253,6 +265,7 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio _ByteCount = 2 * format.ChannelCount; _BytesPerSecond = format.SamplesPerSecond * _ByteCount; _CurrentTime = 0f; + _SyncTimer.Pause(); _SyncTimer.Time = _CurrentTime; PortAudioSharp.PortAudio.PaStreamParameters? outputParams = new PortAudioSharp.PortAudio.PaStreamParameters @@ -283,7 +296,6 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio //From now on closing the driver and the decoder is handled by the thread ONLY! _Paused = true; - _Waiting = true; _FileOpened = true; _Data = new CRingBuffer(_Bufsize); _NoMoreData = false; @@ -299,7 +311,7 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio { _SetStart = time; _SetSkip = true; - _Waiting = true; + _EventDecode.Set(); } } @@ -311,10 +323,8 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio _Decoder.SetPosition(_Start); _CurrentTime = _Start; _TimeCode = _Start; - _Data = new CRingBuffer(_Bufsize); + _Data.Reset(); _NoMoreData = false; - _EventDecode.Set(); - _Waiting = false; _SyncTimer.Time = _Start; } } @@ -323,35 +333,27 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio { while (!_Terminated) { - if (_EventDecode.WaitOne(10)) + lock (_LockSyncSignals) { - lock (_LockSyncSignals) + if (_SetSkip) { - if (_SetSkip) - { - _Skip = true; - _EventDecode.Set(); - _Waiting = true; - } - + _Skip = true; _SetSkip = false; - - _Start = _SetStart; - _Loop = _SetLoop; } - if (_Skip) - { - _DoSkip(); - _Skip = false; - } - - if (!_Waiting) - { - _DoDecode(); - _Update(); - } + _Start = _SetStart; + _Loop = _SetLoop; } + + if (_Skip) + { + _DoSkip(); + _Skip = false; + } + + _DoDecode(); + _Update(); + _EventDecode.WaitOne(); } _DoFree(); @@ -402,12 +404,7 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio _Data.Write(buffer); _TimeCode = timecode; if (_Data.BytesNotRead < _Beginrefill) - { - _Waiting = false; _EventDecode.Set(); - } - else - _Waiting = true; } } @@ -438,7 +435,7 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio { try { - Marshal.Copy(buf, 0, output, (int)frameCount * _ByteCount); + Marshal.Copy(buf, 0, output, buf.Length); } catch (Exception e) { @@ -462,13 +459,8 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio } } - if (_Data.BytesNotRead < _Beginrefill) - { + if (_Data.BytesNotRead < _Beginrefill && !_NoMoreData) _EventDecode.Set(); - _Waiting = false; - } - else - _Waiting = true; float latency = buf.Length / _BytesPerSecond + CConfig.AudioLatency / 1000f; float time = _TimeCode - _Data.BytesNotRead / _BytesPerSecond - latency; @@ -483,7 +475,7 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio } catch (Exception e) { - CLog.LogError("Error PortAudio.treamCallback: " + e.Message); + CLog.LogError("Error PortAudio.StreamCallback: " + e.Message); } return PortAudioSharp.PortAudio.PaStreamCallbackResult.paContinue; @@ -517,11 +509,25 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio public void Dispose() { - if (_EventDecode != null) + _Dispose(true); + GC.SuppressFinalize(this); + } + + private void _Dispose(bool disposing) + { + Close(); + if (disposing) { - _EventDecode.Close(); - _EventDecode = null; - GC.SuppressFinalize(this); + if (_DecoderThread != null) + { + _DecoderThread.Join(); + _DecoderThread = null; + } + if (_EventDecode != null) + { + _EventDecode.Close(); + _EventDecode = null; + } } } } diff --git a/Vocaluxe/Lib/Sound/Playback/PortAudio/CPt1.cs b/Vocaluxe/Lib/Sound/Playback/PortAudio/CPt1.cs index 17b92f45..ea854457 100644 --- a/Vocaluxe/Lib/Sound/Playback/PortAudio/CPt1.cs +++ b/Vocaluxe/Lib/Sound/Playback/PortAudio/CPt1.cs @@ -1,4 +1,21 @@ -using System.Diagnostics; +#region license +// This file is part of Vocaluxe. +// +// Vocaluxe is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Vocaluxe is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Vocaluxe. If not, see . +#endregion + +using System.Diagnostics; namespace Vocaluxe.Lib.Sound.Playback.PortAudio { diff --git a/Vocaluxe/Lib/Sound/Playback/PortAudio/CSyncTimer.cs b/Vocaluxe/Lib/Sound/Playback/PortAudio/CSyncTimer.cs index 2b405c9c..1b4eb0cc 100644 --- a/Vocaluxe/Lib/Sound/Playback/PortAudio/CSyncTimer.cs +++ b/Vocaluxe/Lib/Sound/Playback/PortAudio/CSyncTimer.cs @@ -1,4 +1,21 @@ -using System; +#region license +// This file is part of Vocaluxe. +// +// Vocaluxe is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Vocaluxe is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Vocaluxe. If not, see . +#endregion + +using System; using System.Diagnostics; namespace Vocaluxe.Lib.Sound.Playback.PortAudio diff --git a/Vocaluxe/Lib/Sound/Record/CDelayTest.cs b/Vocaluxe/Lib/Sound/Record/CDelayTest.cs index a9974c40..456885d9 100644 --- a/Vocaluxe/Lib/Sound/Record/CDelayTest.cs +++ b/Vocaluxe/Lib/Sound/Record/CDelayTest.cs @@ -1,4 +1,20 @@ -using System.Diagnostics; +#region license +// This file is part of Vocaluxe. +// +// Vocaluxe is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Vocaluxe is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Vocaluxe. If not, see . +#endregion + using Vocaluxe.Base; namespace Vocaluxe.Lib.Sound.Record @@ -9,11 +25,11 @@ namespace Vocaluxe.Lib.Sound.Record { public int Channel; public bool Finished; + public float OrigThreshold; } private const float _MaxDelayTime = 1000; public bool Running { get; private set; } - private readonly Stopwatch _Timer = new Stopwatch(); private int _Stream = -1; private readonly SDelayChannel[] _DelaysChannel; @@ -34,24 +50,38 @@ namespace Vocaluxe.Lib.Sound.Record Reset(); for (int i = 0; i < _DelaysChannel.Length; i++) { - if (i < channels.Length) + if (i < channels.Length && channels[i] >= 0) { _DelaysChannel[i].Finished = false; _DelaysChannel[i].Channel = channels[i]; + _DelaysChannel[i].OrigThreshold = CRecord.GetVolumeThreshold(channels[i]); + CRecord.SetVolumeThreshold(channels[i], _DelaysChannel[i].OrigThreshold / 3); } else - _DelaysChannel[i].Finished = true; + _DelaysChannel[i].Channel = -1; } _Stream = CSound.PlaySound(ESounds.T440, false); Running = true; } + private void _Stop() + { + if (!Running) + return; + Running = false; + _CloseStream(); + foreach (SDelayChannel delay in _DelaysChannel) + { + if (delay.Channel >= 0) + CRecord.SetVolumeThreshold(delay.Channel, delay.OrigThreshold); + } + } + public void Reset() { - Running = false; + _Stop(); for (int i = 0; i < _DelaysChannel.Length; i++) Delays[i] = 0; - _CloseStream(); } private void _CloseStream() @@ -67,24 +97,21 @@ namespace Vocaluxe.Lib.Sound.Record { if (!Running) return; - if (!_Timer.IsRunning) - { - if (CSound.GetPosition(_Stream) > 0f) - _Timer.Restart(); - } - if (!_Timer.IsRunning) + + float time = CSound.GetPosition(_Stream) * 1000f; + if (time <= 0f) return; bool isActive = false; - if (_Timer.ElapsedMilliseconds <= _MaxDelayTime) + if (time <= _MaxDelayTime) { for (int i = 0; i < _DelaysChannel.Length; i++) { if (_DelaysChannel[i].Channel < 0 || _DelaysChannel[i].Finished) continue; - if (CRecord.GetMaxVolume(_DelaysChannel[i].Channel) > 0.1f && CRecord.GetTone(_DelaysChannel[i].Channel) == 9) + if (CRecord.GetTone(_DelaysChannel[i].Channel) == 9) { - Delays[i] = (int)_Timer.ElapsedMilliseconds; + Delays[i] = (int)time; _DelaysChannel[i].Finished = true; } else @@ -92,11 +119,7 @@ namespace Vocaluxe.Lib.Sound.Record } } if (!isActive) - { - Running = false; - _CloseStream(); - _Timer.Stop(); - } + _Stop(); } } } \ No newline at end of file diff --git a/Vocaluxe/Lib/Sound/Record/CRecordBase.cs b/Vocaluxe/Lib/Sound/Record/CRecordBase.cs index 5dd64987..62c67da7 100644 --- a/Vocaluxe/Lib/Sound/Record/CRecordBase.cs +++ b/Vocaluxe/Lib/Sound/Record/CRecordBase.cs @@ -5,7 +5,7 @@ using Vocaluxe.Base; namespace Vocaluxe.Lib.Sound.Record { /// - /// Base class to implement common functionality for Record classes + /// Base class to implement common functionality for Record classes /// abstract class CRecordBase { @@ -53,7 +53,7 @@ namespace Vocaluxe.Lib.Sound.Record } /// - /// Procedure to be called by descendent classes with data that got recorded + /// Procedure to be called by descendent classes with data that got recorded /// /// Device from which the data was recorded /// Recorded samples, assume Int16 and interleaved for multi-channels @@ -125,6 +125,19 @@ namespace Vocaluxe.Lib.Sound.Record return _Initialized ? _Buffer[player].MaxVolume : 0f; } + public float GetVolumeThreshold(int player) + { + return _Initialized ? _Buffer[player].VolTreshold : 0f; + } + + public void SetVolumeThreshold(int player, float threshold) + { + if (!_Initialized) + return; + + _Buffer[player].VolTreshold = threshold; + } + public bool ToneValid(int player) { return _Initialized && _Buffer[player].ToneValid; diff --git a/Vocaluxe/Lib/Sound/Record/DirectSound/CSampleDataEventArgs.cs b/Vocaluxe/Lib/Sound/Record/DirectSound/CSampleDataEventArgs.cs index 22a9fcd1..b52911e4 100644 --- a/Vocaluxe/Lib/Sound/Record/DirectSound/CSampleDataEventArgs.cs +++ b/Vocaluxe/Lib/Sound/Record/DirectSound/CSampleDataEventArgs.cs @@ -1,4 +1,21 @@ -using System; +#region license +// This file is part of Vocaluxe. +// +// Vocaluxe is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Vocaluxe is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Vocaluxe. If not, see . +#endregion + +using System; namespace Vocaluxe.Lib.Sound.Record.DirectSound { diff --git a/Vocaluxe/Lib/Sound/Record/DirectSound/CSoundCardSource.cs b/Vocaluxe/Lib/Sound/Record/DirectSound/CSoundCardSource.cs index b3a7d5c4..50858b15 100644 --- a/Vocaluxe/Lib/Sound/Record/DirectSound/CSoundCardSource.cs +++ b/Vocaluxe/Lib/Sound/Record/DirectSound/CSoundCardSource.cs @@ -1,4 +1,21 @@ -using System; +#region license +// This file is part of Vocaluxe. +// +// Vocaluxe is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Vocaluxe is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Vocaluxe. If not, see . +#endregion + +using System; using System.Collections.Generic; using System.Threading; using SlimDX.DirectSound; diff --git a/Vocaluxe/Lib/Sound/Record/IRecord.cs b/Vocaluxe/Lib/Sound/Record/IRecord.cs index 04899008..7f020daa 100644 --- a/Vocaluxe/Lib/Sound/Record/IRecord.cs +++ b/Vocaluxe/Lib/Sound/Record/IRecord.cs @@ -62,84 +62,100 @@ namespace Vocaluxe.Lib.Sound.Record interface IRecord { /// - /// Initializes recording + /// Initializes recording /// /// True on success bool Init(); /// - /// Closes recording. You must not use it before calling Init again + /// Closes recording. You must not use it before calling Init again /// void Close(); /// - /// Starts recording on all enabled devices (PlayerChannelX set) + /// Starts recording on all enabled devices (PlayerChannelX set) /// /// True on success, false on error or not initialized bool Start(); /// - /// Stops recording on all devices + /// Stops recording on all devices /// /// True on success, false on error or not initialized bool Stop(); /// - /// Analyzes the buffer for the given player + /// Analyzes the buffer for the given player /// /// void AnalyzeBuffer(int player); /// - /// Get the current raw tone value for a player + /// Get the current raw tone value for a player /// /// 0-based player index /// Tone between 0 and NumHalftones-1 int GetToneAbs(int player); /// - /// Get the current tone value for a player + /// Get the current tone value for a player /// /// 0-based player index /// Tone between 0 and 11 (one octave) int GetTone(int player); /// - /// DEBUG ONLY: Sets a tone for a player + /// DEBUG ONLY: Sets a tone for a player /// /// 0-based player index /// Raw tone value between 0 and NumHalfTones-1 void SetTone(int player, int tone); /// - /// Get the current maximum input volume (normalized) for a player + /// Get the current maximum input volume (normalized) for a player /// /// 0-based player index /// Maximum volume between 0 and 1 float GetMaxVolume(int player); /// - /// Returns whether the current tone is valid. That includes, if maximum volume is higher than the threshold + /// Gets the treshold for detecting silence + /// Value (0-1) for which everything below is considered silence + /// 0-based player index + /// Threshold + /// + float GetVolumeThreshold(int player); + + /// + /// Sets the treshold for detecting silence + /// Value (0-1) for which everything below is considered silence + /// 0-based player index + /// Threshold + /// + void SetVolumeThreshold(int player, float threshold); + + /// + /// Returns whether the current tone is valid. That includes, if maximum volume is higher than the threshold /// /// 0-based player index /// True if tone is detected and volume higher than threshold bool ToneValid(int player); /// - /// Returns the number of half tones used for the raw tone detection + /// Returns the number of half tones used for the raw tone detection /// /// number of half tones used for the raw tone detection int NumHalfTones(); /// - /// Returns the tone weights for a player as an array of normalized values for each halftone + /// Returns the tone weights for a player as an array of normalized values for each halftone /// /// 0-based player index /// Array of values (0-1) with one entry per halftone float[] ToneWeigth(int player); /// - /// Readonly list of all detected record devices. Modifying the devices should not be done when record is running. + /// Readonly list of all detected record devices. Modifying the devices should not be done when record is running. /// /// Readonly list of all detected record devices ReadOnlyCollection RecordDevices(); diff --git a/Vocaluxe/Lib/Video/Acinerella/CDecoderThread.cs b/Vocaluxe/Lib/Video/Acinerella/CDecoderThread.cs index 2b254b98..0ff06799 100644 --- a/Vocaluxe/Lib/Video/Acinerella/CDecoderThread.cs +++ b/Vocaluxe/Lib/Video/Acinerella/CDecoderThread.cs @@ -1,4 +1,21 @@ -using System; +#region license +// This file is part of Vocaluxe. +// +// Vocaluxe is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Vocaluxe is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Vocaluxe. If not, see . +#endregion + +using System; using System.IO; using System.Runtime.InteropServices; using System.Threading; @@ -170,7 +187,7 @@ namespace Vocaluxe.Lib.Video.Acinerella } /// - /// Gets a frame + /// Gets a frame /// /// Referenz to texture where frame should be put in (can be null, then texture is created) /// Maximum start time for frame diff --git a/Vocaluxe/Lib/Webcam/CAForgeNet.cs b/Vocaluxe/Lib/Webcam/CAForgeNet.cs index b07c9f46..13bc4d20 100644 --- a/Vocaluxe/Lib/Webcam/CAForgeNet.cs +++ b/Vocaluxe/Lib/Webcam/CAForgeNet.cs @@ -15,6 +15,7 @@ // along with Vocaluxe. If not, see . #endregion +using System; using AForge.Video; using AForge.Video.DirectShow; using System.Collections.Generic; @@ -31,66 +32,33 @@ namespace Vocaluxe.Lib.Webcam private readonly List _Devices = new List(); private bool _Paused; private VideoCaptureDevice _Webcam; - private FilterInfoCollection _WebcamDevices; private SWebcamConfig _Config; - private byte[] _Data = new byte[1]; + private byte[] _Data; private static readonly object _MutexData = new object(); private int _Width, _Height; - - public void Close() - { - if (_Webcam == null) - return; - _Webcam.SignalToStop(); - _Webcam.WaitForStop(); - _Webcam.NewFrame -= _OnFrame; - _Data = new byte[1]; - } - - public bool GetFrame(ref CTexture frame) - { - lock (_MutexData) - { - if (_Webcam != null && _Width > 0 && _Height > 0 && _Data.Length == _Width * _Height * 4) - CDraw.UpdateOrAddTexture(ref frame, _Width, _Height, _Data); - } - return false; - } - - public Bitmap GetBitmap() - { - if (_Webcam != null && _Width > 0 && _Height > 0 && _Data.Length == _Height * _Width * 4) - { - lock (_MutexData) - { - var bmp = new Bitmap(_Width, _Height); - BitmapData bitmapdata = bmp.LockBits(new Rectangle(0, 0, _Width, _Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); - Marshal.Copy(_Data, 0, bitmapdata.Scan0, _Data.Length); - bmp.UnlockBits(bitmapdata); - return bmp; - } - } - return null; - } + private bool _NewFrameAvailable; + private bool _IsCapturing; public bool Init() { - _WebcamDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice); - foreach (FilterInfo info in _WebcamDevices) + FilterInfoCollection webcams = new FilterInfoCollection(FilterCategory.VideoInputDevice); + foreach (FilterInfo info in webcams) { + var tmpdev = new VideoCaptureDevice(info.MonikerString); + if (tmpdev.VideoCapabilities.Length == 0) + continue; var device = new SWebcamDevice { Name = info.Name, MonikerString = info.MonikerString, - Capabilities = new List() + Capabilities = new List(tmpdev.VideoCapabilities.Length) }; - var tmpdev = new VideoCaptureDevice(info.MonikerString); foreach (VideoCapabilities capabilities in tmpdev.VideoCapabilities) { var item = new SCapabilities { - Framerate = capabilities.FrameRate, + Framerate = capabilities.AverageFrameRate, Height = capabilities.FrameSize.Height, Width = capabilities.FrameSize.Width }; @@ -101,44 +69,188 @@ namespace Vocaluxe.Lib.Webcam return true; } - private void _OnFrame(object sender, NewFrameEventArgs e) + public void Close() { - if (_Paused) + DeSelect(); + _Devices.Clear(); + } + + public void DeSelect() + { + if (_Webcam == null) return; + _Webcam.Stop(); + _Webcam.NewFrame -= _OnFrame; + _IsCapturing = false; lock (_MutexData) { - if (_Width != e.Frame.Width || _Height != e.Frame.Height || _Data.Length != e.Frame.Width * e.Frame.Height * 4) - _Data = new byte[4 * e.Frame.Width * e.Frame.Height]; - - _Width = e.Frame.Width; - _Height = e.Frame.Height; - BitmapData bitmapdata = e.Frame.LockBits(new Rectangle(0, 0, _Width, _Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); - Marshal.Copy(bitmapdata.Scan0, _Data, 0, _Data.Length); - e.Frame.UnlockBits(bitmapdata); + _Data = null; + _Webcam = null; } } - public void Pause() + #region ConfigSelection + private static float _GetScore(int value, int valueRequested) { - if (_Webcam != null) - _Paused = true; + if (valueRequested <= 0) + return 1; + return 1.0f - (float)Math.Abs(value - valueRequested) / Math.Max(value, valueRequested); + } + + private static VideoCapabilities _SelectWebcamConfig(VideoCapabilities[] capabilities, SWebcamConfig config) + { + int configTaken = 0; + if (config.Framerate != 0 && config.Height != 0 && config.Width != 0) + { + float bestMatchScore = 0; + for (int i = 0; i < capabilities.Length; i++) + { + float score = _GetScore(capabilities[i].AverageFrameRate, config.Framerate); + score += _GetScore(capabilities[i].FrameSize.Height, config.Height); + score += _GetScore(capabilities[i].FrameSize.Width, config.Width); + if (score >= bestMatchScore) + { + // Take the config with the best score, Higher indizes should indicate a better resolution + // so choose the last one with best score if 2 have equal scores + bestMatchScore = score; + configTaken = i; + } + } + } + + return capabilities[configTaken]; + } + #endregion + + public bool Select(SWebcamConfig config) + { + //Close old camera connection + DeSelect(); + + if (_Devices.Count < 1) + return false; + + string moniker = _Devices[0].MonikerString; + if (config.MonikerString != "") + { + foreach (SWebcamDevice device in _Devices) + { + if (device.MonikerString == config.MonikerString) + { + moniker = device.MonikerString; + break; + } + } + } + _Webcam = new VideoCaptureDevice(moniker); + + _Webcam.VideoResolution = _SelectWebcamConfig(_Webcam.VideoCapabilities, config); + + _Config.Framerate = _Webcam.VideoResolution.AverageFrameRate; + _Config.Height = _Webcam.VideoResolution.FrameSize.Height; + _Config.Width = _Webcam.VideoResolution.FrameSize.Width; + _Config.MonikerString = _Webcam.Source; + + return true; } public void Start() { if (_Webcam == null) return; - _Webcam.NewFrame -= _OnFrame; - //Subscribe to NewFrame event - _Webcam.NewFrame += _OnFrame; - _Webcam.Start(); - _Paused = false; + if (_IsCapturing) + { + if (_Paused) + { + _Webcam.NewFrame += _OnFrame; + _Paused = false; + } + } + else + { + //Subscribe to NewFrame event + _Webcam.NewFrame += _OnFrame; + _Paused = false; + _Webcam.Start(); + _IsCapturing = true; + } + } + + public void Pause() + { + if (_Webcam != null && !_Paused) + { + _Webcam.NewFrame -= _OnFrame; + lock (_MutexData) //Make sure all events are finished or not yet startet for consistency + { + _Paused = true; + } + } } public void Stop() { if (_Webcam != null) + { _Webcam.SignalToStop(); + _Webcam.NewFrame -= _OnFrame; + lock (_MutexData) //Make sure all events are finished or not yet startet for consistency + { + _IsCapturing = false; + } + } + } + + public bool GetFrame(ref CTexture frame) + { + lock (_MutexData) + { + if (_Data != null && _Data.Length == _Width * _Height * 4 && _NewFrameAvailable) + { + CDraw.UpdateOrAddTexture(ref frame, _Width, _Height, _Data); + _NewFrameAvailable = false; + return true; + } + return false; + } + } + + public Bitmap GetBitmap() + { + lock (_MutexData) + { + if (_Data != null && _Data.Length == _Width * _Height * 4) + { + var bmp = new Bitmap(_Width, _Height); + BitmapData bitmapdata = bmp.LockBits(new Rectangle(0, 0, _Width, _Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); + Marshal.Copy(_Data, 0, bitmapdata.Scan0, _Data.Length); + bmp.UnlockBits(bitmapdata); + return bmp; + } + return null; + } + } + + private void _OnFrame(object sender, NewFrameEventArgs e) + { + if (_Paused) + return; + if (e.Frame.Width == 0 || e.Frame.Height == 0) + return; + lock (_MutexData) + { + if (!IsCapturing()) + return; + if (_Data == null || _Data.Length != e.Frame.Width * e.Frame.Height * 4) + _Data = new byte[e.Frame.Width * e.Frame.Height * 4]; + + _Width = e.Frame.Width; + _Height = e.Frame.Height; + BitmapData bitmapdata = e.Frame.LockBits(new Rectangle(0, 0, _Width, _Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); + Marshal.Copy(bitmapdata.Scan0, _Data, 0, _Data.Length); + e.Frame.UnlockBits(bitmapdata); + _NewFrameAvailable = true; + } } public SWebcamDevice[] GetDevices() @@ -148,42 +260,12 @@ namespace Vocaluxe.Lib.Webcam public bool IsDeviceAvailable() { - return _Devices.Count > 0; + return _Webcam != null; } public bool IsCapturing() { - return _Webcam.IsRunning; - } - - public bool Select(SWebcamConfig config) - { - //Close old camera connection - Close(); - - if (_WebcamDevices == null) - return false; - if (_WebcamDevices.Count < 1) - return false; - - //No MonikerString found, try first webcam - _Webcam = config.MonikerString == "" ? new VideoCaptureDevice(_WebcamDevices[0].MonikerString) : new VideoCaptureDevice(config.MonikerString); - - if (_Webcam == null) - return false; - - if (config.Framerate != 0 && config.Height != 0 && config.Width != 0) - { - _Webcam.DesiredFrameRate = config.Framerate; - _Webcam.DesiredFrameSize = new Size(config.Width, config.Height); - } - - _Config.Framerate = _Webcam.DesiredFrameRate; - _Config.Height = _Webcam.DesiredFrameSize.Height; - _Config.Width = _Webcam.DesiredFrameSize.Width; - _Config.MonikerString = _Webcam.Source; - - return true; + return _IsCapturing && !_Paused; } public SWebcamConfig GetConfig() diff --git a/Vocaluxe/Lib/Webcam/IWebcam.cs b/Vocaluxe/Lib/Webcam/IWebcam.cs index aa108411..98ae1804 100644 --- a/Vocaluxe/Lib/Webcam/IWebcam.cs +++ b/Vocaluxe/Lib/Webcam/IWebcam.cs @@ -46,19 +46,33 @@ namespace Vocaluxe.Lib.Webcam interface IWebcam { bool Init(); + void Close(); void Start(); void Pause(); void Stop(); - void Close(); + /// + /// Gets last captured frame. Returns true if frame was updated
+ /// Note that this will invalidate the last frame and not return it again with this function + ///
+ /// + /// bool GetFrame(ref CTexture frame); + + /// + /// Gets the last captured frame as a bitma + /// + /// + /// Null if no frame was captured, the bitmap otherwise Bitmap GetBitmap(); + SWebcamConfig GetConfig(); SWebcamDevice[] GetDevices(); bool IsDeviceAvailable(); bool IsCapturing(); bool Select(SWebcamConfig webcamConfig); + void DeSelect(); } } \ No newline at end of file diff --git a/Vocaluxe/Program.cs b/Vocaluxe/Program.cs index 74464be9..5ee3826e 100644 --- a/Vocaluxe/Program.cs +++ b/Vocaluxe/Program.cs @@ -268,6 +268,7 @@ namespace Vocaluxe CDraw.Unload(); CDataBase.Close(); CWebcam.Close(); + GC.Collect(); // Do a GC run here before we close logs to have finalizers run CLog.CloseAll(); } catch (Exception) {} diff --git a/Vocaluxe/Screens/CScreenNames.cs b/Vocaluxe/Screens/CScreenNames.cs index f3789e5c..945e6731 100644 --- a/Vocaluxe/Screens/CScreenNames.cs +++ b/Vocaluxe/Screens/CScreenNames.cs @@ -547,7 +547,7 @@ namespace Vocaluxe.Screens for (int i = 1; i <= CGame.NumPlayer; i++) { CRecord.AnalyzeBuffer(i - 1); - _Equalizers["EqualizerPlayer" + i].Update(CRecord.ToneWeigth(i - 1)); + _Equalizers["EqualizerPlayer" + i].Update(CRecord.ToneWeigth(i - 1), CRecord.GetMaxVolume(i - 1)); } return true; } diff --git a/Vocaluxe/Screens/CScreenOptionsRecord.cs b/Vocaluxe/Screens/CScreenOptionsRecord.cs index cd41ebaf..1a658fe5 100644 --- a/Vocaluxe/Screens/CScreenOptionsRecord.cs +++ b/Vocaluxe/Screens/CScreenOptionsRecord.cs @@ -223,25 +223,29 @@ namespace Vocaluxe.Screens if (_CheckMicConfig()) { - _ChannelEnergy[0] = 0f; - int player = _SelectSlides[_SelectSlideRecordChannel1].Selection; - if (player > 0) + int player = _SelectSlides[_SelectSlideRecordChannel1].Selection - 1; + if (player >= 0) { - _ChannelEnergy[0] = CRecord.GetMaxVolume(player - 1); - _Equalizers[_EqualizerChannel1].Update(CRecord.ToneWeigth(player - 1)); + _ChannelEnergy[0] = CRecord.GetMaxVolume(player); + _Equalizers[_EqualizerChannel1].Update(CRecord.ToneWeigth(player), CRecord.GetMaxVolume(player)); } else + { + _ChannelEnergy[0] = 0f; _Equalizers[_EqualizerChannel1].Reset(); + } - _ChannelEnergy[1] = 0f; - player = _SelectSlides[_SelectSlideRecordChannel2].Selection; - if (player > 0) + player = _SelectSlides[_SelectSlideRecordChannel2].Selection - 1; + if (player >= 0) { - _ChannelEnergy[1] = CRecord.GetMaxVolume(player - 1); - _Equalizers[_EqualizerChannel2].Update(CRecord.ToneWeigth(player - 1)); + _ChannelEnergy[1] = CRecord.GetMaxVolume(player); + _Equalizers[_EqualizerChannel2].Update(CRecord.ToneWeigth(player), CRecord.GetMaxVolume(player)); } else + { + _ChannelEnergy[1] = 0f; _Equalizers[_EqualizerChannel2].Reset(); + } } else { diff --git a/Vocaluxe/Screens/CScreenOptionsSound.cs b/Vocaluxe/Screens/CScreenOptionsSound.cs index 8e417a2c..8f087207 100644 --- a/Vocaluxe/Screens/CScreenOptionsSound.cs +++ b/Vocaluxe/Screens/CScreenOptionsSound.cs @@ -150,16 +150,17 @@ namespace Vocaluxe.Screens { CConfig.GameMusicVolume = _SelectSlides[_SelectSlideGameMusicVolume].Selection * 5; CConfig.PreviewMusicVolume = _SelectSlides[_SelectSlidePreviewMusicVolume].Selection * 5; - CConfig.BackgroundMusic=(EOffOn)_SelectSlides[_SelectSlideBackgroundMusic].Selection; + CConfig.BackgroundMusic = (EOffOn)_SelectSlides[_SelectSlideBackgroundMusic].Selection; CConfig.BackgroundMusicSource = (EBackgroundMusicSource)_SelectSlides[_SelectSlideBackgroundMusicSource].Selection; - CConfig.BackgroundMusicVolume= _SelectSlides[_SelectSlideBackgroundMusicVolume].Selection * 5; + CConfig.BackgroundMusicVolume = _SelectSlides[_SelectSlideBackgroundMusicVolume].Selection * 5; CConfig.SaveConfig(); CBackgroundMusic.SetMusicSource(CConfig.BackgroundMusicSource); CBackgroundMusic.SetVolume(CConfig.BackgroundMusicVolume); if (CConfig.BackgroundMusic == EOffOn.TR_CONFIG_ON) CBackgroundMusic.Play(); - else CBackgroundMusic.Pause(); + else + CBackgroundMusic.Pause(); } } } \ No newline at end of file diff --git a/Vocaluxe/Screens/CScreenOptionsVideo.cs b/Vocaluxe/Screens/CScreenOptionsVideo.cs index d1b446c8..a2bf330d 100644 --- a/Vocaluxe/Screens/CScreenOptionsVideo.cs +++ b/Vocaluxe/Screens/CScreenOptionsVideo.cs @@ -30,7 +30,7 @@ namespace Vocaluxe.Screens // Version number for theme files. Increment it, if you've changed something on the theme files! protected override int _ScreenVersion { - get { return 4; } + get { return 5; } } private const string _SelectSlideVideoBackgrounds = "SelectSlideVideoBackgrounds"; @@ -45,6 +45,9 @@ namespace Vocaluxe.Screens private const string _ButtonScreenAdjustments = "ButtonScreenAdjustments"; private const string _ButtonExit = "ButtonExit"; + private const string _TextWebcams = "TextWebcams"; + private const string _TextWebcamResolution = "TextWebcamResolution"; + private SWebcamConfig _Config; private CTexture _WebcamTexture; private int _DeviceNr; @@ -61,6 +64,7 @@ namespace Vocaluxe.Screens _SelectSlideVideoBackgrounds, _SelectSlideVideoPreview, _SelectSlideVideosInSongs, _SelectSlideVideosToBackground, _SelectSlideWebcamDevices, _SelectSlideWebcamCapabilities }; + _ThemeTexts = new string[] {_TextWebcams, _TextWebcamResolution}; } public override void LoadTheme(string xmlPath) @@ -154,8 +158,8 @@ namespace Vocaluxe.Screens public override bool UpdateGame() { - CWebcam.GetFrame(ref _WebcamTexture); - _Statics[_StaticWebcamOutput].Texture = _WebcamTexture; + if (CWebcam.GetFrame(ref _WebcamTexture)) + _Statics[_StaticWebcamOutput].Texture = _WebcamTexture; _SelectSlides[_SelectSlideVideosToBackground].Selection = (int)CConfig.VideosToBackground; return true; } @@ -170,7 +174,7 @@ namespace Vocaluxe.Screens public override void OnClose() { base.OnClose(); - CWebcam.Close(); + CWebcam.Stop(); } public override void OnShow() @@ -189,25 +193,20 @@ namespace Vocaluxe.Screens { if (devices != null && devices.Length > 0) { - _DeviceNr = 0; - _CapabilityNr = 0; - _GetFirstConfiguredWebcamDevice(ref _DeviceNr, ref _CapabilityNr); - foreach (SWebcamDevice d in devices) _SelectSlides[_SelectSlideWebcamDevices].AddValue(d.Name); - _SelectSlides[_SelectSlideWebcamDevices].Selection = _DeviceNr; - foreach (SCapabilities c in devices[_DeviceNr].Capabilities) - _SelectSlides[_SelectSlideWebcamCapabilities].AddValue(c.Width + " x " + c.Height + " @ " + c.Framerate + " FPS "); - _Config.MonikerString = devices[_SelectSlides[_SelectSlideWebcamDevices].Selection].MonikerString; - _Config.Width = devices[_SelectSlides[_SelectSlideWebcamDevices].Selection].Capabilities[_SelectSlides[_SelectSlideWebcamCapabilities].Selection].Width; - _Config.Height = devices[_SelectSlides[_SelectSlideWebcamDevices].Selection].Capabilities[_SelectSlides[_SelectSlideWebcamCapabilities].Selection].Height; - _Config.Framerate = - devices[_SelectSlides[_SelectSlideWebcamDevices].Selection].Capabilities[_SelectSlides[_SelectSlideWebcamCapabilities].Selection].Framerate; - CWebcam.Close(); - CWebcam.Select(CConfig.WebcamConfig); - CWebcam.Start(); - ssVisible = true; + int devNr; + int capNr; + if (_GetFirstConfiguredWebcamDevice(out devNr, out capNr)) + { + _SelectSlides[_SelectSlideWebcamDevices].Selection = devNr; + _OnDeviceEvent(); + _SelectSlides[_SelectSlideWebcamCapabilities].Selection = capNr; + _OnCapabilitiesEvent(); + + ssVisible = true; + } } } catch (Exception e) @@ -218,6 +217,8 @@ namespace Vocaluxe.Screens _SelectSlides[_SelectSlideWebcamDevices].Visible = ssVisible; _SelectSlides[_SelectSlideWebcamCapabilities].Visible = ssVisible; _Statics[_StaticWebcamOutput].Visible = ssVisible; + _Texts[_TextWebcams].Visible = ssVisible; + _Texts[_TextWebcamResolution].Visible = ssVisible; } private void _SaveConfig() @@ -239,7 +240,6 @@ namespace Vocaluxe.Screens { _SelectSlides[_SelectSlideWebcamCapabilities].Clear(); _DeviceNr = _SelectSlides[_SelectSlideWebcamDevices].Selection; - _CapabilityNr = 0; SWebcamDevice d = CWebcam.GetDevices()[_DeviceNr]; for (int i = 0; i < d.Capabilities.Count; i++) @@ -247,16 +247,8 @@ namespace Vocaluxe.Screens _SelectSlides[_SelectSlideWebcamCapabilities].AddValue(d.Capabilities[i].Width + " x " + d.Capabilities[i].Height + " @ " + d.Capabilities[i].Framerate + "FPS"); } - _SelectSlides[_SelectSlideWebcamCapabilities].Selection = 0; - - _Config.MonikerString = d.MonikerString; - _Config.Width = d.Capabilities[_SelectSlides[_SelectSlideWebcamCapabilities].Selection].Width; - _Config.Height = d.Capabilities[_SelectSlides[_SelectSlideWebcamCapabilities].Selection].Height; - _Config.Framerate = d.Capabilities[_SelectSlides[_SelectSlideWebcamCapabilities].Selection].Framerate; - - CWebcam.Close(); - CWebcam.Select(_Config); - CWebcam.Start(); + _CapabilityNr = -1; + _OnCapabilitiesEvent(); } } @@ -266,24 +258,27 @@ namespace Vocaluxe.Screens { _CapabilityNr = _SelectSlides[_SelectSlideWebcamCapabilities].Selection; - SWebcamDevice d = CWebcam.GetDevices()[_SelectSlides[_SelectSlideWebcamDevices].Selection]; + SWebcamDevice d = CWebcam.GetDevices()[_DeviceNr]; _Config.MonikerString = d.MonikerString; - _Config.Width = d.Capabilities[_SelectSlides[_SelectSlideWebcamCapabilities].Selection].Width; - _Config.Height = d.Capabilities[_SelectSlides[_SelectSlideWebcamCapabilities].Selection].Height; - _Config.Framerate = d.Capabilities[_SelectSlides[_SelectSlideWebcamCapabilities].Selection].Framerate; + _Config.Width = d.Capabilities[_CapabilityNr].Width; + _Config.Height = d.Capabilities[_CapabilityNr].Height; + _Config.Framerate = d.Capabilities[_CapabilityNr].Framerate; - CWebcam.Close(); CWebcam.Select(_Config); CWebcam.Start(); } } - private void _GetFirstConfiguredWebcamDevice(ref int device, ref int capabilities) + private bool _GetFirstConfiguredWebcamDevice(out int device, out int capabilities) { SWebcamDevice[] devices = CWebcam.GetDevices(); if (devices == null) - return; + { + device = -1; + capabilities = -1; + return false; + } for (int i = 0; i < devices.Length; i++) { @@ -296,10 +291,13 @@ namespace Vocaluxe.Screens { device = i; capabilities = j; - return; + return true; } } } + device = 0; + capabilities = 0; + return true; } } } \ No newline at end of file diff --git a/Vocaluxe/Screens/CScreenProfiles.cs b/Vocaluxe/Screens/CScreenProfiles.cs index 9039f293..2c29383d 100644 --- a/Vocaluxe/Screens/CScreenProfiles.cs +++ b/Vocaluxe/Screens/CScreenProfiles.cs @@ -141,13 +141,13 @@ namespace Vocaluxe.Screens } else if (_Buttons[_ButtonDelete].Selected) _DeleteProfile(); - else if (_Buttons[_ButtonWebcam].Selected && CWebcam.IsDeviceAvailable()) + else if (_Buttons[_ButtonWebcam].Selected) _OnWebcam(); - else if (_Buttons[_ButtonSaveSnapshot].Selected && CWebcam.IsDeviceAvailable()) + else if (_Buttons[_ButtonSaveSnapshot].Selected) _OnSaveSnapshot(); - else if (_Buttons[_ButtonDiscardSnapshot].Selected && CWebcam.IsDeviceAvailable()) + else if (_Buttons[_ButtonDiscardSnapshot].Selected) _OnDiscardSnapshot(); - else if (_Buttons[_ButtonTakeSnapshot].Selected && CWebcam.IsDeviceAvailable()) + else if (_Buttons[_ButtonTakeSnapshot].Selected) _OnTakeSnapshot(); break; @@ -235,13 +235,13 @@ namespace Vocaluxe.Screens CProfiles.SetActive(_SelectSlides[_SelectSlideProfiles].ValueIndex, (EOffOn)_SelectSlides[_SelectSlideActive].Selection); } - else if (_Buttons[_ButtonWebcam].Selected && CWebcam.IsDeviceAvailable()) + else if (_Buttons[_ButtonWebcam].Selected) _OnWebcam(); - else if (_Buttons[_ButtonSaveSnapshot].Selected && CWebcam.IsDeviceAvailable()) + else if (_Buttons[_ButtonSaveSnapshot].Selected) _OnSaveSnapshot(); - else if (_Buttons[_ButtonDiscardSnapshot].Selected && CWebcam.IsDeviceAvailable()) + else if (_Buttons[_ButtonDiscardSnapshot].Selected) _OnDiscardSnapshot(); - else if (_Buttons[_ButtonTakeSnapshot].Selected && CWebcam.IsDeviceAvailable()) + else if (_Buttons[_ButtonTakeSnapshot].Selected) _OnTakeSnapshot(); } @@ -270,15 +270,16 @@ namespace Vocaluxe.Screens int avatarID = CProfiles.GetAvatarID(_SelectSlides[_SelectSlideProfiles].ValueIndex); _SelectSlides[_SelectSlideAvatars].SetSelectionByValueIndex(avatarID); - if (CWebcam.IsDeviceAvailable() && CWebcam.IsCapturing()) + if (_Snapshot == null) { - if (_Snapshot == null) - CWebcam.GetFrame(ref _WebcamTexture); - - _Statics[_StaticAvatar].Texture = _WebcamTexture; + if (CWebcam.IsCapturing()) + { + if (CWebcam.GetFrame(ref _WebcamTexture)) + _Statics[_StaticAvatar].Texture = _WebcamTexture; + } + else + _Statics[_StaticAvatar].Texture = CProfiles.GetAvatarTexture(avatarID); } - else - _Statics[_StaticAvatar].Texture = CProfiles.GetAvatarTexture(avatarID); } return true; @@ -310,22 +311,36 @@ namespace Vocaluxe.Screens private void _OnTakeSnapshot() { - _Buttons[_ButtonSaveSnapshot].Visible = true; - _Buttons[_ButtonDiscardSnapshot].Visible = true; - _Buttons[_ButtonWebcam].Visible = false; - _Buttons[_ButtonTakeSnapshot].Visible = false; - _Snapshot = CWebcam.GetBitmap(); + if (!CWebcam.IsDeviceAvailable()) + { + CDraw.RemoveTexture(ref _WebcamTexture); + _Snapshot = null; + _Buttons[_ButtonSaveSnapshot].Visible = false; + _Buttons[_ButtonDiscardSnapshot].Visible = false; + _Buttons[_ButtonTakeSnapshot].Visible = false; + _Buttons[_ButtonWebcam].Visible = false; + } + else + { + CWebcam.Stop(); //Do this first to get consistent frame and bitmap + _Snapshot = CWebcam.GetBitmap(); + if (CWebcam.GetFrame(ref _WebcamTexture)) + _Statics[_StaticAvatar].Texture = _WebcamTexture; + _Buttons[_ButtonSaveSnapshot].Visible = true; + _Buttons[_ButtonDiscardSnapshot].Visible = true; + _Buttons[_ButtonTakeSnapshot].Visible = false; + _Buttons[_ButtonWebcam].Visible = false; + } } private void _OnDiscardSnapshot() { - CWebcam.Stop(); - CDraw.RemoveTexture(ref _WebcamTexture); _Snapshot = null; + CDraw.RemoveTexture(ref _WebcamTexture); _Buttons[_ButtonSaveSnapshot].Visible = false; _Buttons[_ButtonDiscardSnapshot].Visible = false; _Buttons[_ButtonTakeSnapshot].Visible = false; - _Buttons[_ButtonWebcam].Visible = true; + _Buttons[_ButtonWebcam].Visible = CWebcam.IsDeviceAvailable(); } private void _OnSaveSnapshot() @@ -339,13 +354,12 @@ namespace Vocaluxe.Screens _Snapshot.Save(filename, ImageFormat.Png); _Snapshot = null; - CWebcam.Stop(); CDraw.RemoveTexture(ref _WebcamTexture); _Buttons[_ButtonSaveSnapshot].Visible = false; _Buttons[_ButtonDiscardSnapshot].Visible = false; _Buttons[_ButtonTakeSnapshot].Visible = false; - _Buttons[_ButtonWebcam].Visible = true; + _Buttons[_ButtonWebcam].Visible = CWebcam.IsDeviceAvailable(); int id = CProfiles.NewAvatar(filename); CProfiles.SetAvatar(_SelectSlides[_SelectSlideProfiles].ValueIndex, id); @@ -354,9 +368,13 @@ namespace Vocaluxe.Screens private void _OnWebcam() { + if (!CWebcam.IsDeviceAvailable()) + { + _Buttons[_ButtonWebcam].Visible = false; + return; + } _Snapshot = null; CWebcam.Start(); - CWebcam.GetFrame(ref _WebcamTexture); _Buttons[_ButtonSaveSnapshot].Visible = false; _Buttons[_ButtonDiscardSnapshot].Visible = false; _Buttons[_ButtonTakeSnapshot].Visible = true; @@ -449,7 +467,7 @@ namespace Vocaluxe.Screens foreach (CAvatar avatar in avatars) { _SelectSlides[_SelectSlideAvatars].AddValue( - Path.GetFileName(avatar.FileName), + avatar.GetDisplayName(), null, avatar.ID, -1); diff --git a/Vocaluxe/Screens/CScreenSing.cs b/Vocaluxe/Screens/CScreenSing.cs index 32e0442e..c7956c9c 100644 --- a/Vocaluxe/Screens/CScreenSing.cs +++ b/Vocaluxe/Screens/CScreenSing.cs @@ -235,7 +235,7 @@ namespace Vocaluxe.Screens case Keys.W: if (CWebcam.IsDeviceAvailable()) { - _Webcam = !_Webcam; + _Webcam = !CWebcam.IsCapturing(); if (_Webcam) CWebcam.Start(); else @@ -756,7 +756,7 @@ namespace Vocaluxe.Screens CParty.FinishedSinging(); if (_Webcam) - CWebcam.Close(); + CWebcam.Stop(); } private int _FindCurrentLine(CVoice voice, CSongLine[] lines, CSong song) diff --git a/Vocaluxe/Vocaluxe.csproj b/Vocaluxe/Vocaluxe.csproj index f43e6307..eea26470 100644 --- a/Vocaluxe/Vocaluxe.csproj +++ b/Vocaluxe/Vocaluxe.csproj @@ -219,6 +219,7 @@ + diff --git a/VocaluxeLib/CFading.cs b/VocaluxeLib/CFading.cs index 0b6761cb..e66c10db 100644 --- a/VocaluxeLib/CFading.cs +++ b/VocaluxeLib/CFading.cs @@ -43,7 +43,7 @@ namespace VocaluxeLib } /// - /// Gets the current value and sets finished + /// Gets the current value and sets finished /// /// Set to whether fading has finished /// Current value (between from and to values) diff --git a/VocaluxeLib/CHelper.cs b/VocaluxeLib/CHelper.cs index 77c8f729..9d37b818 100644 --- a/VocaluxeLib/CHelper.cs +++ b/VocaluxeLib/CHelper.cs @@ -162,7 +162,7 @@ namespace VocaluxeLib } /// - /// Returns a list with all files in the given path that match a given pattern + /// Returns a list with all files in the given path that match a given pattern /// /// Path to search for /// Pattern to match (e.g. "*.jpg") @@ -195,7 +195,7 @@ namespace VocaluxeLib } /// - /// Returns a list with all files in the given path that matches at least one of the given patterns + /// Returns a list with all files in the given path that matches at least one of the given patterns /// /// Path to search for /// List of patterns to match @@ -212,7 +212,7 @@ namespace VocaluxeLib } /// - /// Returns a list with all image files in the given path + /// Returns a list with all image files in the given path /// /// Path to search for /// Search directories recursively @@ -224,7 +224,7 @@ namespace VocaluxeLib } /// - /// Returns a list with all image files in the given path + /// Returns a list with all image files in the given path /// /// Path to search for /// Search directories recursively diff --git a/VocaluxeLib/Menu/CEqualizer.cs b/VocaluxeLib/Menu/CEqualizer.cs index 5d75a478..58680d90 100644 --- a/VocaluxeLib/Menu/CEqualizer.cs +++ b/VocaluxeLib/Menu/CEqualizer.cs @@ -22,7 +22,7 @@ namespace VocaluxeLib.Menu { enum EEqualizerStyle { - Collums + Columns } struct SThemeEqualizer @@ -64,6 +64,8 @@ namespace VocaluxeLib.Menu } private float[] _Bars; + private int _MaxBar; + private float _MaxVolume; public CEqualizer(int partyModeID) { @@ -211,17 +213,31 @@ namespace VocaluxeLib.Menu return false; } - public void Update(float[] weights) + public void Update(float[] weights, float volume) { if (weights == null || weights.Length == 0 || _Bars == null) return; + if (volume < 0.001) + return; + if (volume > _MaxVolume) + _MaxVolume = volume; + _MaxBar = 0; + float maxVal = -99f; for (int i = 0; i < _Bars.Length; i++) { if (weights.Length > i) { - _Bars[i] = 1f - weights[i]; if (_Theme.DrawNegative == EOffOn.TR_CONFIG_OFF && weights[i] < 0) - _Bars[i] = 1f + weights[i]; + _Bars[i] = 0f; + else + { + _Bars[i] = weights[i] * volume / _MaxVolume; + if (_Bars[i] > maxVal) + { + maxVal = _Bars[i]; + _MaxBar = i; + } + } } else _Bars[i] = 0f; @@ -235,30 +251,22 @@ namespace VocaluxeLib.Menu for (int i = 0; i < _Bars.Length; i++) _Bars[i] = 0f; + _MaxBar = 0; + _MaxVolume = 0f; } public void Draw() { - if (_Bars == null || _Theme.Style != EEqualizerStyle.Collums) + if (_Bars == null || _Theme.Style != EEqualizerStyle.Columns) return; float dx = Rect.W / _Bars.Length; - int max = _Bars.Length - 1; - float maxB = _Bars[max]; - for (int i = 0; i < _Bars.Length - 1; i++) - { - if (_Bars[i] > maxB) - { - maxB = _Bars[i]; - max = i; - } - } for (int i = 0; i < _Bars.Length; i++) { var bar = new SRectF(Rect.X + dx * i, Rect.Y + Rect.H - _Bars[i] * Rect.H, dx - Space, _Bars[i] * Rect.H, Rect.Z); SColorF color = Color; - if (i == max) + if (i == _MaxBar) color = MaxColor; CBase.Drawing.DrawColor(color, bar); diff --git a/VocaluxeLib/Profile/CAvatar.cs b/VocaluxeLib/Profile/CAvatar.cs index 9418a034..1daba02e 100644 --- a/VocaluxeLib/Profile/CAvatar.cs +++ b/VocaluxeLib/Profile/CAvatar.cs @@ -15,6 +15,8 @@ // along with Vocaluxe. If not, see . #endregion +using System.Diagnostics; +using System.IO; using VocaluxeLib.Draw; namespace VocaluxeLib.Profile @@ -22,8 +24,9 @@ namespace VocaluxeLib.Profile public class CAvatar { public int ID; - private string _FileName = ""; + private readonly string _FileName = ""; private CTexture _Texture; + private const int _MaxNameLen = 12; public CTexture Texture { @@ -42,13 +45,9 @@ namespace VocaluxeLib.Profile private CAvatar(CTexture texture, string fileName, int id = -1) { - ID = id; - } - - public bool LoadFromFile(string fileName) - { + _Texture = texture; _FileName = fileName; - return Reload(); + ID = id; } public bool Reload() @@ -63,5 +62,14 @@ namespace VocaluxeLib.Profile { CBase.Drawing.RemoveTexture(ref _Texture); } + + public string GetDisplayName() + { + string name = Path.GetFileNameWithoutExtension(_FileName); + Debug.Assert(name != null); + if (name.Length > _MaxNameLen) + name = name.Substring(0, _MaxNameLen); + return name; + } } } \ No newline at end of file diff --git a/VocaluxeLib/Songs/CSongWriter.cs b/VocaluxeLib/Songs/CSongWriter.cs index a36e3fe6..7d5eb4ca 100644 --- a/VocaluxeLib/Songs/CSongWriter.cs +++ b/VocaluxeLib/Songs/CSongWriter.cs @@ -122,6 +122,35 @@ namespace VocaluxeLib.Songs _Tw.WriteLine(addLine); } + /// + /// Gets a good beat for a line break that is >=firstPossibleBeat and <firstNoteBeat + /// Based on algorithm used by YASS: http://www.yass-along.com/errors.html + /// + /// First beat that is possible for a line break (equal (just after) previous line note end) + /// First note beat on current line + /// A good beat for the line break + private int _GetBreakBeat(int firstPossibleBeat, int firstNoteBeat) + { + int breakBeat; + int diff = firstNoteBeat - firstPossibleBeat; + float timeDiff = CBase.Game.GetTimeFromBeats(diff, _Song.BPM); + if (timeDiff > 4f) + breakBeat = firstPossibleBeat + (int)CBase.Game.GetBeatFromTime(2f, _Song.BPM, 0f); + else if (timeDiff > 2f) + breakBeat = firstPossibleBeat + (int)CBase.Game.GetBeatFromTime(1f, _Song.BPM, 0f); + else if (diff < 2) + breakBeat = firstPossibleBeat; + else if (diff < 9) + breakBeat = firstNoteBeat - 2; + else if (diff < 13) + breakBeat = firstNoteBeat - 3; + else if (diff < 17) + breakBeat = firstNoteBeat - 4; + else + breakBeat = firstPossibleBeat + 12; + return breakBeat; + } + private void _WriteNotes() { for (int i = 0; i < _Song.Notes.VoiceCount; i++) @@ -129,13 +158,13 @@ namespace VocaluxeLib.Songs CVoice voice = _Song.Notes.GetVoice(i); if (_Song.Notes.VoiceCount > 1) _Tw.WriteLine("P" + Math.Pow(2, i)); - bool firstLine = true; int currentBeat = 0; + CSongLine lastLine = null; foreach (CSongLine line in voice.Lines) { - if (!firstLine) + if (lastLine != null) { - string lineTxt = "- " + (line.StartBeat - currentBeat); + string lineTxt = "- " + (_GetBreakBeat(lastLine.EndBeat + 1, line.FirstNoteBeat) - currentBeat); if (_Song.Relative) { lineTxt += " " + (line.FirstNoteBeat - currentBeat); @@ -143,8 +172,6 @@ namespace VocaluxeLib.Songs } _Tw.WriteLine(lineTxt); } - else - firstLine = false; foreach (CSongNote note in line.Notes) { string tag; @@ -164,6 +191,7 @@ namespace VocaluxeLib.Songs } _Tw.WriteLine(tag + " " + (note.StartBeat - currentBeat) + " " + note.Duration + " " + note.Tone + " " + note.Text); } + lastLine = line; } } _Tw.WriteLine("E"); @@ -177,11 +205,21 @@ namespace VocaluxeLib.Songs _WriteHeader(); _WriteNotes(); } + catch (UnauthorizedAccessException) + { + CBase.Log.LogError("Cannot write " + filePath + ". Directory might be readonly or requires admin rights."); + return false; + } catch (Exception e) { CBase.Log.LogError("Unhandled exception while writing " + filePath + ": " + e); return false; } + finally + { + if (_Tw != null) + _Tw.Dispose(); + } return true; } } diff --git a/VocaluxeLib/VocaluxeLib.csproj b/VocaluxeLib/VocaluxeLib.csproj index 5a6f5a21..3e17ea26 100644 --- a/VocaluxeLib/VocaluxeLib.csproj +++ b/VocaluxeLib/VocaluxeLib.csproj @@ -14,29 +14,7 @@ 512 Client
- - AnyCPU - true - full - false - bin\ - TRACE;DEBUG;WIN - prompt - 4 - Off - - - AnyCPU - none - true - bin\ - prompt - 4 - false - WIN - Off - - + AnyCPU true full @@ -48,7 +26,7 @@ Off ..\CheckingRules.ruleset - + AnyCPU none true @@ -59,7 +37,7 @@ WIN Off - + AnyCPU true full @@ -70,7 +48,7 @@ 4 Off - + AnyCPU none true @@ -81,39 +59,7 @@ LINUX Off - - AnyCPU - true - full - false - bin\ - TRACE;DEBUG;LINUX - prompt - 4 - Off - - - AnyCPU - none - true - bin\ - prompt - 4 - false - LINUX - Off - - - bin\ - WIN - true - AnyCPU - false - Off - prompt - ManagedMinimumRules.ruleset - - + bin\ WIN true diff --git a/WebserverInitalConfig/CConfigHttpApi.cs b/WebserverInitalConfig/CConfigHttpApi.cs index e16f3a44..e13a9cda 100644 --- a/WebserverInitalConfig/CConfigHttpApi.cs +++ b/WebserverInitalConfig/CConfigHttpApi.cs @@ -128,7 +128,7 @@ namespace WebserverInitalConfig CngKey key; try { - key= CngKey.Create(CngAlgorithm2.Rsa, Guid.NewGuid().ToString(), keyParam); + key = CngKey.Create(CngAlgorithm2.Rsa, Guid.NewGuid().ToString(), keyParam); } catch (PlatformNotSupportedException) {