summaryrefslogtreecommitdiffstats
path: root/nebu/audio/SoundSystem.cpp
blob: e57bb9120090c95da96c07cc8932f9fb6dc7edca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include "audio/nebu_SoundSystem.h"

#include <string.h>

namespace Sound {
  System::System(SDL_AudioSpec *spec) { 
    _spec = spec;
    _sources.next = NULL; 

    _info.format = _spec->format;
    _info.rate = spec->freq;
    _info.channels = spec->channels;
    
    _mix_music = 1; // TODO: add 'master' volume for music and fx
    _mix_fx = 1;

    _status = 0; // sound system is not initialized
  }

  void System::Callback(Uint8* data, int len) {
    // printf("callback got called for %d bytes of data\n", len);

    // ensure silence
    memset(data, 0, len);

    if(_status == eUninitialized) 
      return;

    List* p;
    int sources_mixed = 0;
    for(p = & _sources; p->next != NULL; p = p->next) {
      Source* s = (Source*) p->data;
      if(s->IsPlaying()) {
				// fprintf(stderr, "mixing source\n");
				if(!(
						 (s->GetType() & eSoundFX && ! _mix_fx ) ||
						 (s->GetType() & eSoundMusic && ! _mix_music) )
					 )
					{
						if( s->Mix(data, len) )
							sources_mixed++;
					}
				// fprintf(stderr, "done mixing %d sources\n", sources_mixed);
      }
    }
  }

  void System::AddSource(Source* source) { 
    List* p;
    for(p = & _sources; p->next != NULL; p = p->next);
    p->next = new List;
    p->next->next = NULL;
    p->data = source;
  }

  void System::Idle(void) {
		/* idle processing */
		List *p;
		for(p = & _sources; p->next != NULL; p = p->next) {
			Source *source = (Source*) p->data;
			// check if source is removable & has stopped playing
			if(source->IsRemovable() && !source->IsPlaying()) {
				// get rid of data
				p->data = p->next->data;
				List *tmp = p->next;
				p->next = p->next->next;
				delete tmp;
				delete source;
				if(p->next == NULL)
					break;
			} else {
				source->Idle();
			}
		}
	}

	extern "C" {
    void c_callback(void *userdata, Uint8 *stream, int len) { 
      // printf("c_callback got called for %d bytes of data\n", len);
      ((System*)userdata)->Callback(stream, len);
    }
  }
}