|
how to use play_audio_stream? |
aesteves
Member #12,798
April 2011
|
I want an example where load a wav file and play it, and when it finished sound start again and again and again... I want to use the function play_audio_stream, but I dont know how. I try these, but not soud anything: int main() //create the audio stream //Them create the sample "archivo" loading a wav //when the sound buffer is void: //Put into the buffer the sample "archivo" //Indicate that the buffer is ready I am from uruguay and my english is basic, please write correctly |
Desmond Taylor
Member #11,943
May 2010
|
This may or may not help you but I wrote a basic class that loads, plays and stops audio using ALLEGRO_SAMPLE. 1#ifndef __AUDIO_HPP_INCLUDED
2#define __AUDIO_HPP_INCLUDED
3
4#include <allegro5/allegro_audio.h>
5#include <allegro5/allegro_acodec.h>
6
7struct SAMPLE_DATA
8{
9 ALLEGRO_SAMPLE* sample;
10 ALLEGRO_SAMPLE_ID sample_id;
11};
12
13class Audio
14{
15 public:
16 Audio();
17 ~Audio();
18
19 int load_from_file( std::string filename );
20 void play( int id, ALLEGRO_PLAYMODE loop = ALLEGRO_PLAYMODE_ONCE, float gain = 1.0, float pan = 0.0, float speed = 1.0 );
21 void stop( int id );
22
23 private:
24 std::vector<SAMPLE_DATA> sample;
25 bool is_valid_id( unsigned int id );
26};
27
28#endif // __AUDIO_HPP_INCLUDED
1#include "audio.hpp"
2
3Audio::Audio()
4{
5 if ( !al_install_audio() )
6 exit(-1);
7
8 if ( !al_init_acodec_addon() )
9 exit(-1);
10
11 if ( !al_reserve_samples( 32 ) )
12 exit(-1);
13}
14
15Audio::~Audio()
16{
17 al_stop_samples();
18
19 for ( unsigned int i=0; i<this->sample.size(); i++ )
20 {
21 if ( this->sample[i].sample )
22 al_destroy_sample( this->sample[i].sample );
23 }
24
25 al_uninstall_audio();
26}
27
28int Audio::load_from_file( std::string filename )
29{
30 ALLEGRO_SAMPLE* temp_sample = al_load_sample( filename.c_str() );
31 if ( temp_sample )
32 {
33 SAMPLE_DATA sd;
34 sd.sample = temp_sample;
35 this->sample.push_back( sd );
36 return this->sample.size() - 1;
37 }
38
39 return -1;
40}
41
42void Audio::play( int id, ALLEGRO_PLAYMODE loop, float gain, float pan, float speed )
43{
44 if ( this->is_valid_id( id ) )
45 {
46 al_play_sample( this->sample[id].sample, gain, pan, speed, loop, &this->sample[id].sample_id );
47 }
48}
49
50void Audio::stop( int id )
51{
52 if ( this->is_valid_id( id ) )
53 {
54 al_stop_sample( &this->sample[id].sample_id );
55 }
56}
57
58bool Audio::is_valid_id( unsigned int id )
59{
60 if ( id < 0 || id >= this->sample.size() )
61 return false;
62
63 if ( !this->sample[id].sample )
64 return false;
65
66 return true;
67}
1#include <allegro5/allegro.h>
2
3// Include the audio header.
4#include "audio.hpp"
5
6int main()
7{
8 al_init();
9
10 // Create an audio pointer. This also initializes allegro audio addons.
11 // Must be called after al_init().
12 Audio* audio = new Audio();
13
14 // Load the audio file.
15 int sound_id = audio->load_from_file( "music.wav" );
16 if ( sound_id == -1 ) // Returns -1 on failure.
17 exit(-1);
18
19 // Play the sound using the returned sound_id.
20 audio->play( sound_id, ALLEGRO_PLAYMODE_LOOP );
21
22 // You need to add something here to stop the program ending else you shall not hear anything.
23 al_rest( 10000 ); // Rest for 10 seconds for now :)
24
25 return 0;
26}
Hope this helps getting sound to work. Append: I haven't tested this code myself since I am now going to bed. Must be up for the kids in the morning. |
aesteves
Member #12,798
April 2011
|
I want do it want do it with play_audio_stream my reason: |
Desmond Taylor
Member #11,943
May 2010
|
I never read that I shall have to add it to my class at some point for music files |
Edgar Reynaldo
Major Reynaldo
May 2007
|
aesteves said:
1int main()
2{
3 allegro_init();
4 install_keyboard();
5 install_sound(DIGI_AUTODETECT, MIDI_AUTODETECT, NULL);
6
7 //create the audio stream
8 AUDIOSTREAM *stream = play_audio_stream(1024, 8, FALSE, 22050, 255, 128);
9
10 //Them create the sample "archivo" loading a wav
11 SAMPLE *archivo=load_wav("wav.wav");
12 while(!key[KEY_ESC]){
13 void *mem_chunk;
14 mem_chunk = get_audio_stream_buffer(stream);
15
16 //when the sound buffer is void:
17 if (mem_chunk != NULL){
18
19 //Put into the buffer the sample "archivo"
20 mem_chunk=&archivo; 21
22 //Indicate that the buffer is ready
23 free_audio_stream_buffer(stream);
24 }
25 }
26}
The line 'mem_chunk = &archivo;' does nothing. You have to fill the buffer using the pointer provided to you by get_audio_stream_buffer. Example : 1 int length = 1024;// 1024 frames of data
2 int bits = 8;// 8 bit data
3 int stereo = 0;// mono data
4 int freq = 22050;// 22050 samples per second
5 int vol = 255;
6 int pan = 127;
7
8// AUDIOSTREAM *play_audio_stream(int len, int bits, int stereo, int freq, int vol, int pan);
9 AUDIOSTREAM *stream = play_audio_stream(1024, 8, FALSE, 22050, 255, 128);
10
11 void* mem_chunk;
12 mem_chunk = get_audio_stream_buffer(stream);
13 int bytes = length * (bits / 8) * (stereo ? 2 : 1)
14 if (mem_chunk) {
15 for (int i = 0 ; i < bytes ; ++i) {
16 mem_chunk[i] = SoundData();// However you generate your data
17 }
18 }
If you're going to use SAMPLE*s, then use the routines for playing samples - play_sample. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
aesteves
Member #12,798
April 2011
|
it give me an error: I put 3 lines to your example to generate my data: #include <allegro.h> int main() int length = 1024; void* mem_chunk; thank you for the reply |
Edgar Reynaldo
Major Reynaldo
May 2007
|
aesteves said:
`void*' is not a pointer-to-object type void* mem_chunk; mem_chunk = get_audio_stream_buffer(stream); int bytes = length * (bits / 8) * (stereo ? 2 : 1); if (mem_chunk) { for (int i = 0 ; i < bytes ; ++i) { mem_chunk[i] = data[i];
Sorry, I mislead you. Before you can assign values to the array returned by get_audio_stream_buffer, you must cast it to a specific type. Since you are using a 8 bit mono stream, then you want to cast it to an unsigned char*. The manual said: The sample data are always in unsigned format. This means that you need to convert your data from signed format into unsigned format. So, before you had this : aesteves said:
char data[1024]; for(int i=0;i<1024;i++) data[i]=sin(i*2*PI/10)*127;//I create the wave, 1 cycle per 10 sampes
But now you should have this : unsigned char data[1024]; for (int i = 0 ; i < 1024 ; ++i) { float raw = sin((float)i*2.0f*M_PI/10.0); unsigned char d = (unsigned char)((raw*127.5f) + 127.5f); data[i] = d; }
Edit My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
aesteves
Member #12,798
April 2011
|
ok thank I want to know if allegro in the code use 1 or 2 buffers for the sound??? |
Edgar Reynaldo
Major Reynaldo
May 2007
|
There are two buffers for the AUDIOSTREAM : The manual said: You can think of an AUDIOSTREAM structure as a wrapper around two audio buffers. The first thing you do is fill both buffers with sound data and let Allegro play them. Once the first buffer has been played, the second starts, and Allegro lets you know you have to fill the other one (i.e. graphics double buffering applied to sounds too big to fit into memory). So fill both when you start the stream, and then only fill the other buffer when get_audio_stream_buffer returns non-null. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
aesteves
Member #12,798
April 2011
|
Can I use more than 2 buffers? I want to make a piano, and I am thinking use 1 buffer per musical note, beacause of these way I should not to refill the buffers and is would be more efficient and fast. I only would need to indicate what buffer play. Beacuse I made a litle program that play a sound with AUDIOSTREAM, and when I order to change the sound, the program takes too long (you know that the speed is very important in a piano) |
Edgar Reynaldo
Major Reynaldo
May 2007
|
aesteves said: Can I use more than 2 buffers? Not with an AUDIOSTREAM, no. You can make your own 'buffers' and then copy them into your AUDIOSTREAM buffer though. aesteves said: I want to make a piano, and I am thinking use 1 buffer per musical note, beacause of these way I should not to refill the buffers and is would be more efficient and fast. I only would need to indicate what buffer play. You could make your own SAMPLE's, modifying the SAMPLE::data array after making a new sample with create_sample. Then you could just use play_sample. aesteves said: Beacuse I made a litle program that play a sound with AUDIOSTREAM, and when I order to change the sound, the program takes too long (you know that the speed is very important in a piano)
aesteves said:
//AUDIOSTREAM *play_audio_stream(int len, int bits, int stereo, int freq, int vol, int pan); AUDIOSTREAM *stream = play_audio_stream(1024, 8, FALSE, 22050, 255, 128);
The reason it takes so long to hear the sound again is because you are not filling the buffer fast enough. With only 1024 frames in the buffer at 22050 frames per second, you need to refill the buffer (22050/1024 ~= 21) 21 times every second. You can either use a larger number of frames (len) and refill it less often (which will make the sound take longer to change), or you can continue to use a small number of frames and update the sound more often. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
aesteves
Member #12,798
April 2011
|
I taste what you said, but it doesn't change. Look at these example, I can set the variable whit values bigers or smollers than 1024, but there arent change. The example has to play the note1 or note2 if the key z is presed or not 1#include <allegro.h>
2#include <string.h>
3#include <math.h>
4
5int main()
6{
7 allegro_init();
8 install_keyboard();
9 set_gfx_mode(GFX_AUTODETECT_WINDOWED, 300, 200, 0, 0);
10 install_sound(DIGI_AUTODETECT, MIDI_AUTODETECT, NULL);
11
12 int TAMANIODELBUFFER=1024;//Set the buffer's size
13
14 AUDIOSTREAM *stream = play_audio_stream(TAMANIODELBUFFER, 8, FALSE, 22050,255, 128);
15 unsigned char nota1[16];//Declare the notes
16 unsigned char nota2[16];
17 for(int j=0;j<16;j++) nota1[j]=sin(j*2*3.14159/8)*127+127;//Create the notes
18 for(int j=0;j<16;j++) nota2[j]=sin(j*2*3.14159/16)*127+127;
19 unsigned char buf[TAMANIODELBUFFER];
20 void *mem_chunk;
21 int pos=0;
22 int tecla=0;
23 while(!key[KEY_ESC]){
24 mem_chunk = get_audio_stream_buffer(stream);
25 if(mem_chunk != NULL){
26 if(key[KEY_Z]) for(int j=0;j<TAMANIODELBUFFER;j++) {buf[j]=nota2[(j+pos)%(16)]; if(j==TAMANIODELBUFFER-1) pos=(j+pos+1)%(16);}
27 else for(int j=0;j<TAMANIODELBUFFER;j++) {buf[j]=nota1[(j+pos)%(16)]; if(j==TAMANIODELBUFFER-1) pos=(j+pos+1)%(16);}
28 memcpy(mem_chunk, buf, sizeof(char)*TAMANIODELBUFFER );
29 free_audio_stream_buffer(stream);
30 }
31 }
32}
33END_OF_MAIN();
what is the better way to get a fast reply of the sound about the keyboard? |
Edgar Reynaldo
Major Reynaldo
May 2007
|
I compiled your program and ran it, and there is a noticeable delay when changing sounds. I think this has to do with Allegro's internal mixer buffer size, and I don't believe that can be changed by the user. Sorry. play_sample is much faster for me, and plays pretty much immediately after a key press for me. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
|