0x666 napisał(a)
Dobra, zrobiłem szybki test i... Access violation reading location 0xffffffff przy wywoływaniu destruktora. Bez znaczenia, czy wave się załadował, czy też nie.
hmmm... u mnie coś takiego się nie robiło, czyżby dodanie, runtime do DLL mogło to powodować? hmmm ale co ma sie runtime do kody klasy... Sprawdzę to w najbliższym czasie ale raczej nie dziś...
0x666 napisał(a)
Następna sprawa to to, że zrobiłeś naiwny (czyt. bez zrozumienia struktury plików RIFF) sposób czytania plików wave. Na twoim przykładowym samplu działa, ale na moim już nie ;)
Twój przykład ma taką strukturę:
RIFF
└ WAVE
├ fmt
└ data
i to jest podstawowa struktura pliku wav, ale nie jedyna. Format RIFF dopuszcza możliwość wystąpienia dodatkowych bloków, niekoniecznie predefiniowanych, pomiędzy blokiem 'fmt ' i 'data' (być może nawet fmt nie musi być pierwszym blokiem). Mój sampel miał taką strukturę:
RIFF
└ WAVE
├ fmt
├ PAD (4kB)
└ data
...i efekt wiadomo jaki ;)
ta wiem, funkcja ta stara jeszcze z czasów początków pisania tej klasy, prawie nic tam nie zmieniałem oprócz czytania z memory dla zasobów, poprawi się ;) (WINDOWS/Media(w PCM) działają i wygenerowane przez WavePad pliki tez mi działały), ale wiem zmienię
albo już na zapas pytanie żebym nie musiał szukać, czy pomiędzy blokami mogą występować występować puste przestrzenie, powiedzmy wypełnione 0, bo to utrudni, będę musiał szukać następnego znanego identyfikatora po bajcie, a tak to można założyć, że po zakończeniu wielkości bloki, od razu powinien być identyfikator i jego wielkość i dla nieznanego przeskoczył bym sobie o odczytaną wielkość bez szukania, a i spodziewać się możliwości wystąpienia bloku fmt po data? czy fmt musi być pierwsze?
0x666 napisał(a)
class __declspec(dllexport) CWinWave
{
public:
[...]
//do not call this
DWORD ThreadProc();
[...]
};
Cóż stało na przeszkodzie zrobić tą metodę prywatną?
jest to klasowy odpowiednik ThreadProc, w CreateThread parametrem musi być statyczna funkcja, a zrobiłem to tak, że tej statycznej funkcji przekazuje this klasy (wywołującej nowy wątek) jako parametr i ona wywołuje przez ten parametr metodę ThreadProc, jakby nie patrzeć jest ona wywoływana z zewnątrz klasy przez system, więc musi być publiczna, bo się kompilator będzie burzył... lepszego rozwiązania nie znam
0x666 napisał(a)
oczywiście to nie koniec prac nad tym projektem, a mam nadzieję że dopiero początek :> teraz planuję wyposażyć bibliotekę w konwersję ilości kanałów, następnie w programowy poziom natężenia dźwięku(modyfikowanie wartości próbek o podany współczynnik) [...]
To zacznij od rozdzielenia "engina" audio od strumieni plikowych/pamięciowych/itp. Wykorzystaj możliwości jakie daje polimorfizm, wtedy twoja biblioteka nie będzie się ograniczała tylko do odtwarzania plików wav.
</quote>
nawet chciałem tak zrobić, z każdym kolejnym dziedziczeniem kolejne możliwości miały być dostępne, wyszło mi że koło 10 klas, czyli możliwość streamingu(klasa najwyżej w hierarchii) miała być dziedziczona po 9 klasach :D uznałem jednak że to z lekka przesada, ale jakiś podział musi być rzeczywiście, bo w miarę rozbudowy coraz więcej tych metod w jednej klasie, robi się ciasno ;)
W sumie teraz oddzielę sam "engine" od reszty, bo znacznie zmieni się jego budowa, jak zrobię konwersje kanałów i głębi próbek + modyfikacja natężenia, będzie oddzielny bufor wejściowy i wyjściowy, zapowiada się całkiem inne działanie engina...
W sumie zadowolony jestem bo chociaż jedna osoba się tematem zainteresowała...
EDIT: jeszcze coś, w sumie nie sprawdzałem, a mogłem, czy formatami skompresowanymi(tymi uwzględnionymi w wave, np. ADPCM) zajmie się karta muzyczna, tzn. jeśli wyślę skompresowany bufor bezpośrednio wczytany z pliku, i w WAVEFORMATEX uwzględnię, że to nie PCM, to czydekompresją zajmie się karta/system po wysłaniu tego przez waveOurWrite? cz sam powinienem zająć się dekompresją, bo jeżeli nie, to nie ma powodu ograniczać się tylko do PCM(dopóki w grę nie wchodzi oczywiście zmienianie natężeń itp., bo raczej nie skompresowanych danych nie będę modyfikował)