|
[a5] Memory Management -Bitmaps part 2 |
Phrasz
Member #10,091
August 2008
|
So I thought I was correctly freeing bitmaps ....but: {"name":"check.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/2\/c\/2c0587a4cf1c1d6a979121d0c1e7eb3c.png","w":400,"h":127,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/2\/c\/2c0587a4cf1c1d6a979121d0c1e7eb3c"} The example below is a "book reader" for my kids. The idea is it loads the images and eventually the audio streams for each page. I know the resolution is a bit big (1442, 1024), but I thought it would be fine with reusing the bitmap, freeing the bitmap once done, and then recycling the bitmap for the next image. Everytime I change the page 20-30 MB of RAM is used... 1#include <stdio.h>
2#include <stdlib.h>
3#include "allegro5/allegro.h"
4#include "allegro5/allegro_image.h"
5#include "allegro5/allegro_audio.h"
6#include "allegro5/allegro_acodec.h"
7#include "allegro5/allegro_font.h"
8#include <allegro5/allegro_ttf.h>
9
10//#include "common.c"
11
12int main(int argc, const char *argv[]){
13//------------------------------------------//
14// VARIABLES
15 ALLEGRO_DISPLAY *display;
16 ALLEGRO_BITMAP *membitmap, *bg;//, *bitmap;
17
18 ALLEGRO_TIMER *timer;
19 ALLEGRO_EVENT_QUEUE *queue;
20 bool redraw = true;
21 bool runthisgame=1; //keeps the while loop alive
22 int counter_sixtith_sec=0;
23 int page_num=1;
24 bool page_printed=0;
25 bool song_started=0;
26//------------------------------------------//
27
28
29
30//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~//
31// Allegro Bootup
32//Return if allegro cannot start
33 if (!al_init()) {
34 printf("\nCould not init Allegro.\n");
35 // abort_example("Could not init Allegro.\n");
36 }
37//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~//
38
39
40//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~//
41// I/O Devices Installation
42 al_install_mouse();
43 al_install_keyboard();
44 al_init_image_addon();
45 al_init_font_addon();
46 al_init_ttf_addon();
47//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~//
48
49
50//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~//
51// Display Creation
52
53 display = al_create_display(1442, 1024);
54 if (!display) {
55 printf("Error creating display\n");
56 //abort_example("Error creating display\n");
57 }
58
59 al_set_window_title(display, "How the Gecko Lost His Tail");
60//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~//
61
62
63//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~//
64// Audio Function Variables
65ALLEGRO_SAMPLE *sample;
66ALLEGRO_SAMPLE_INSTANCE *sample_inst;
67
68 al_init_acodec_addon();
69
70 if (!al_install_audio()) {
71 //abort_example("Could not init sound!\n");
72 return 1;
73 }
74
75 if (!al_reserve_samples(1)) {
76 //abort_example("Could not set up voice and mixer.\n");
77 return 1;
78 }
79
80 sample = al_load_sample("music/01_loadsong.ogg");
81 if (!sample) {
82 //abort_example("Could not load sample from '%s'!\n", argv[1]);
83 }
84
85 /* Loop the sample. */
86 //sample_inst = al_create_sample_instance(sample);
87 sample_inst = al_create_sample_instance(sample);
88 al_set_sample_instance_playmode(sample_inst, ALLEGRO_PLAYMODE_LOOP);
89 al_attach_sample_instance_to_mixer(sample_inst, al_get_default_mixer());
90
91//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~//
92
93
94//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~//
95// Timer Function Variables
96 timer = al_create_timer(1.0 / 60); //60 FPS
97 queue = al_create_event_queue();
98 al_register_event_source(queue, al_get_keyboard_event_source());
99 al_register_event_source(queue, al_get_display_event_source(display));
100 al_register_event_source(queue, al_get_timer_event_source(timer));
101 al_start_timer(timer);
102//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~//
103
104//-------------------------------------------------------------//
105// First BITMAP
106
107 al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP);
108 membitmap = al_load_bitmap("images/01.jpg");
109 al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP);
110 bg =al_clone_bitmap(membitmap);
111 al_destroy_bitmap(membitmap);
112 al_destroy_bitmap(bg);
113//-------------------------------------------------------------//
114
115///-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~///
116/// THE MAGIC WHILE LOOP
117/// Here's the start of the execution of the game
118 while (runthisgame==1){//runthisgame) {
119 ALLEGRO_EVENT event;
120 al_wait_for_event(queue, &event);
121
122 if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE){ //User closes the window
123 runthisgame=0;
124 }
125 if (event.type == ALLEGRO_EVENT_KEY_CHAR) {
126 if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE){
127 runthisgame=0;
128 }
129 if (event.keyboard.keycode == ALLEGRO_KEY_LEFT){//Previous Page
130 if(page_num>1){
131 page_num--;page_printed=0;song_started=0;
132 //al_destroy_sample_instance(sample_inst);
133 //al_destroy_sample(sample);
134
135 }
136 }
137 if (event.keyboard.keycode == ALLEGRO_KEY_RIGHT||event.keyboard.keycode == ALLEGRO_KEY_SPACE){//Next Page
138 if(page_num<18){
139 page_num++;page_printed=0;song_started=0;
140 al_destroy_sample_instance(sample_inst);
141 //al_destroy_sample(sample);
142 }
143
144 }
145 }
146 //
147 if (event.type == ALLEGRO_EVENT_TIMER)
148 redraw = true;
149
150 if (redraw && al_is_event_queue_empty(queue)) {
151 redraw = false;
152 ///---MORE MAGIC---///
153 switch(page_num){
154 case 1:
155 if(!page_printed){
156 ///IMAGE
157 membitmap = al_load_bitmap("images/01.jpg");
158 // //al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP);
159 bg =al_clone_bitmap(membitmap);
160 al_destroy_bitmap(membitmap);
161 al_draw_bitmap(bg,0,0,0);
162 al_destroy_bitmap(bg);
163 al_flip_display();
164 ///SOUND
165 if(!song_started){
166 //al_stop_sample_instance(sample_inst);
167 al_set_sample(sample_inst, al_load_sample("music/01_TitleSong.ogg"));
168 al_play_sample_instance(sample_inst);
169 song_started=1;
170 }
171 page_printed=1;
172 }
173 if(counter_sixtith_sec==60*228){ //counter*60== seconds comapre to 228 -->title song is 228 secs (3mins 48sec) long
174 page_num++; //auto go to next page
175 }
176 break;
177
178 .
179 .
180 .
181
182 break;
183 case 18:
184 if(!page_printed){
185 ///IMAGE
186 membitmap = al_load_bitmap("images/18.jpg");
187 //al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP);
188 bg =al_clone_bitmap(membitmap);
189 al_destroy_bitmap(membitmap);
190 al_draw_bitmap(bg,0,0,0);
191 al_destroy_bitmap(bg);
192 al_flip_display();
193 ///SOUND
194 if(!song_started){
195 al_stop_sample_instance(sample_inst);
196 al_set_sample(sample_inst, al_load_sample("music/01_TitleSong.ogg"));
197 al_play_sample_instance(sample_inst);
198 song_started=1;
199 }
200 page_printed=1;
201 }
202 if(counter_sixtith_sec==60*228){ //counter*60== seconds comapre to 228 -->title song is 228 secs (3mins 48sec) long
203 page_num++; //auto go to next page
204 }
205 break;
206
207 default:
208 printf("\nDANGER WILL ROBINSON!!!!");
209 }
210 printf("\nCounter(%i) Page_num(%i), Page_Printed(%i)",counter_sixtith_sec,page_num,page_printed);
211 counter_sixtith_sec++;
212
213 }
214
215 ///----------------///
216
217 }
218///-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~///
219
220
221 //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~//
222 // DATA DESTRUCTION
223 //BITMAP *black, *powered, *PPlogo, *gimp, *presents, *menuscreen;
224 al_destroy_bitmap(bg);
225
226 al_destroy_sample_instance(sample_inst);
227 al_destroy_sample(sample);
228 al_uninstall_audio();
229 //-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~//
230
231
232
233
234 return 0; //Program Completed Successfully
235
236}
The kicker: The largest picture is only 414 KB...any thoughts to the memory issue?
|
torhu
Member #2,727
September 2002
|
You probably have to free the samples too, even if the docs don't say so. |
Phrasz
Member #10,091
August 2008
|
I was thinking that too since I haven't tested "just" the bitmaps. I'll try commenting out the audio, check the results, and then play with the audio after. UPDATE: Next question: How do I properly free audio? (looking at this music post) UPDATE 2:
|
torhu
Member #2,727
September 2002
|
I suppose that would be al_destroy_sample. |
Matthew Leverton
Supreme Loser
January 1999
|
Phrasz said: al_set_sample(sample_inst, al_load_sample("music/01_TitleSong.ogg")); That's not good. Loading a sample uncompresses it into raw data. A 1 MB ogg file could be a 10MB sample when loaded. Furthermore, you are then attaching it to an instance and forgetting about it. So every time that line runs, you lose X MB... where X is the uncompressed size. You don't need to even use sample instances if you simply want to play a clip: al_reserve_samples(16); // sets up a default mixer, and creates 16 sample instances that Allegro manages for you s = al_load_sample("music/01_TitleSong.ogg") al_play_sample(s, ... ); // when finished: al_destroy_sample(s); All that said, if you want to conserve space, just stream the ogg music with al_load_audio_stream(). That way it doesn't need to uncompress the entire thing at once. This works great for background music. Samples should be used for playing sound effects. |
Phrasz
Member #10,091
August 2008
|
Thanks for the response! I've been trying to get the files to stream, but do you know how I would stream multiple files at once?
|
Matthew Leverton
Supreme Loser
January 1999
|
Call the function on two different files... |
Phrasz
Member #10,091
August 2008
|
Gracias... I also looked at the ex_stream_file.c code Now with the streams when I am done I use the al_destroy_audio_stream().
|
Matthew Leverton
Supreme Loser
January 1999
|
|
Phrasz
Member #10,091
August 2008
|
Thanks guys! I now am able to keep the memory below 28 MBs! As far as multiple streams (this is for a future reader) I just used two samples, and then am able to tie the streams to the mixer and detach them / destroy them as needed. IE: Creation Functions 1//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~//
2// Audio Function Variables
3
4ALLEGRO_VOICE* voice;
5ALLEGRO_MIXER* mixer;
6
7 al_init_acodec_addon();
8
9 if (!al_install_audio()) {
10 //abort_example("Could not init sound!\n");
11 return 1;
12 }
13
14 if (!al_reserve_samples(1)) {
15 //abort_example("Could not set up voice and mixer.\n");
16 return 1;
17 }
18
19 voice = al_create_voice(44100, ALLEGRO_AUDIO_DEPTH_INT16, ALLEGRO_CHANNEL_CONF_2);
20 if (!voice) { fprintf(stderr, "Could not create ALLEGRO_VOICE.\n"); return 1; }
21
22 #ifndef BYPASS_MIXER
23 mixer = al_create_mixer(44100, ALLEGRO_AUDIO_DEPTH_FLOAT32, ALLEGRO_CHANNEL_CONF_2);
24 if (!mixer) {
25 fprintf(stderr, "Could not create ALLEGRO_MIXER.\n");
26 return 1;
27 }
28 fprintf(stderr, "Mixer created.\n");
29 if (!al_attach_mixer_to_voice(mixer, voice)){
30 fprintf(stderr, "al_attach_mixer_to_voice failed.\n");
31 return 1;
32 }
33 #endif
34 ALLEGRO_AUDIO_STREAM *stream, *stream2;
35 bool playing = true;
36
37 stream = al_load_audio_stream("music/01_TitleSong.ogg", 4, 2048);
38 al_attach_audio_stream_to_mixer(stream, mixer);
39 stream2 = al_load_audio_stream("music/Page_null.ogg", 4, 2048);
40 al_attach_audio_stream_to_mixer(stream2, mixer);
41
42
43//-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~//
This is to stop a previous stream and load a new one: 1al_destroy_audio_stream(stream);
2stream = al_load_audio_stream("music/01_TitleSong.ogg", 4, 2048);
3al_attach_audio_stream_to_mixer(stream, mixer);
|
Matthew Leverton
Supreme Loser
January 1999
|
The code is still a bit confusing. If you are going to use your own mixer, you should create it before al_reserve_samples() and call al_set_default_mixer() on it before reserving the samples. Otherwise, al_reserve_samples() will create its own mixer and voice. Or, you can do this: al_reserve_samples(10); mixer = al_get_default_mixer(); and then you don't have to create your own mixer or voice. Note that if you never call al_play_sample() then you don't even need to call al_reserve_samples(). |
|