rav_jarosz2 Temat założony przez niniejszego użytkownika |
[Allegro 4] Odtworzenie dźwięku o danej częstotliwości » 2017-04-01 15:34:26 Dzień dobry! Próbuję zrobić prosty kreator muzyki. Nigdy wcześniej nie próbowałem bawić się dźwiękiem. Mam problem z tym, żeby wytworzyć dźwięk "w locie". Nie mam pojęcia dlaczego poniższy kod nie działa. Mógłbym wczytać każdą nutę jako .wav ale nie chcę wczytywać sampli każdego dźwięku, bo to zbyt niewygodne. Pomożecie? :) #include <allegro.h>
int main() { allegro_init(); install_keyboard(); set_color_depth( 32 ); set_gfx_mode( GFX_AUTODETECT_WINDOWED, 800, 600, 0, 0 ); install_sound( DIGI_AUTODETECT, MIDI_AUTODETECT, "" ); set_volume( 255, 255 ); BITMAP * buffer = create_bitmap( 800, 600 ); clear_to_color( buffer, 0x333333 ); play_audio_stream( 1024, 8, FALSE, 440, 255, 128 ); while( !key[ KEY_ESC ] ) { blit( buffer, screen, 0, 0, 0, 0, 800, 600 ); } destroy_bitmap( buffer ); return 0; } END_OF_MAIN();
|
|
j23 |
» 2017-04-01 19:49:45 Nie znam Allegro, ale z pobieżnego przeglądu dokumentacji wychodzi, że powinieneś użyć funkcji get_audio_stream_buffer, żeby uzyskać dostęp do bufora audio, który powinieneś wypełnić próbkami, po czym użyć free_audio_stream_buffer, co by strumień wiedział, że bufor jest gotowy. |
|
rav_jarosz2 Temat założony przez niniejszego użytkownika |
» 2017-04-01 21:20:53 Ehh, nic nie rozumiem z tej dokumentacji. Póki co ominąłem to tak, że utworzyłem sobie w Audacity sampla o częstotliwości 1Khz i trwającym pół sekundy. Potem go wczytałem SAMPLE * dzwiek = load_sample( "1khz.wav" );
A później odtwarzam go 2 razy na sekundę stop_sample( dzwiek ); play_sample( dzwiek, 255, 128, 440, 1 );
Modyfikuję czwarty parametr funkcji żeby zagrać inną częstotliwość (bo bazowa jest 1Khz i mój sampel ma 1Khz, więc jak dam 440 w to miejsce to mój sampel będzie odtworzony z takim zwolnieniem). Niestety sampel trwa też wtedy odpowiednio dłużej (dla 440Hz ponad 2 razy dłużej) dlatego przed odtworzeniem jest zatrzymanie poprzedniego. Ale i tak czekam na lepsze i optymalniejsze ogarnięcie tematu, jeśli ktoś potrafi i chce :) |
|
j23 |
» 2017-04-02 11:33:20 Jeśli chcesz generować dźwięk w locie, to prawdopodobnie musisz użyć funkcji, o których pisałem wcześniej. Co do generowania dźwięku, możesz użyć funkcji sin i generować wartości kolejnych próbek według wzoru: smp[ i ] = sin(2*PI*f*i/sr), gdzie f to częstotliwość w Hz, i to indeks próbki, sr to częstotliwość próbkowania w Hz. Spróbuj tak: unsigned buff_size = 1024; unsigned sample_rate = 44100; unsigned bits = 16; unsigned channels = 1; double freq = 1000;
AUDIOSTREAM * stream = play_audio_stream( buff_size, bits, channels, sample_rate, 255, 128 ); if( stream ) { int i = 0; while( i < 2 * sample_rate ) { int16_t * buf =( int16_t * ) get_audio_stream_buffer( stream ); if( buf != NULL ) { for( int j = 0; j < buff_size; ++j, ++i ) buf[ j ] = int16_t( 32767.* sin( 2.* M_PI * freq * double( i ) / sample_rate ) ); free_audio_stream_buffer( stream ); } std::this_thread::sleep_for( std::chrono::milliseconds( 1 ) ); } }
...
Nie znam Allegro, pisane z palca, więc może nie działać... |
|
rav_jarosz2 Temat założony przez niniejszego użytkownika |
» 2017-04-02 14:14:25 M_PI nie miałem zdefiniowane więc dałem: I zmieniłem tą funkcję std::this_thread::sleep_for( std::chrono::milliseconds( 1 ) );
na Ale wyrzuciło błąd w tej kluczowej linii: conversion from `double' to non-scalar type `fix' requested
Nie mam pojęcia jak to naprawić... PS: Mój programik ten który wytwarza dźwięk modyfikując sampla 1Khz już działa sam w sobie i gra http://chomiczek.uploadfile.pl/pobierz/1058819---gy5b.htmlTylko muszę dodać częstotliwość dla każdej nuty i każdego półtonu (bo teraz odtwarzam 100Hz*wysokość nuty) i będzie git :D (SPACJA- odtwarzanie/stop, LPM-wstawienie nutki, PPM-usunięcie nutki, F1-zapisanie projektu) Ale zmieniłbym chętnie metodę odtwarzania, bo ta jest taka jakaś... |
|
j23 |
» 2017-04-02 19:43:11 M_PI nie miałem zdefiniowane |
Makro jest zdefiniowane w math.h, choć może być zablokowane. Ale wyrzuciło błąd w tej kluczowej linii: |
Być może kompilator nie wie, co to jest int16_t. Dodaj nagłówek <stdint.h>. |
|
rav_jarosz2 Temat założony przez niniejszego użytkownika |
» 2017-04-06 13:24:45 Nooo i cudownie. Działa.
Dzięki wielkie za pomoc :) |
|
« 1 » |