Fixed another bug in output level.
[cantaveria.git] / audio.c
blob85b5abcf5ac86a525a8f2bdf94ca8be10020eae1
1 /*
2 Cantaveria - action adventure platform game
3 Copyright (C) 2009 2010 Evan Rinehart
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to
18 The Free Software Foundation, Inc.
19 51 Franklin Street, Fifth Floor
20 Boston, MA 02110-1301, USA
23 #include <stdlib.h>
24 #include <math.h>
26 #include <SDL/SDL.h>
28 #include <list.h>
29 #include <org.h>
30 #include <synth.h>
31 #include <seq.h>
32 #include <util.h>
33 #include <audio.h>
35 float* lout;
36 float* rout;
38 static int rms_level;
39 static int peak_level;
41 void audio_callback(void *userdata, Uint8 *stream, int bytes){
42 int i, j;
43 Sint16* out = (Sint16*)stream;
44 int buflen = bytes / 2; /* Sint16 = 2 bytes */
45 int samples = buflen / 2; /* 2 channels */
47 float accum = 0;
48 int max = 0;
49 float db = 0;
51 synth_generate(lout, rout, samples);
52 for(i=0, j=0; i<samples; i++){
53 out[j] = (Sint16)(lout[i]*32767); j++;
54 out[j] = (Sint16)(rout[i]*32767); j++;
56 /* output level.
57 dB rms, 20log ( sqrt( avg( x^2 ) ) )
58 dB peak, 20log ( max ( x ) )
61 accum += out[j-1] * out[j-1];
62 if(abs(out[j-1]) > max){
63 max = abs(out[j-1]);
67 accum /= samples;
68 accum = sqrt(accum);
69 db = 20*log10(accum/32767);
70 if(db > -9999){
71 rms_level = db;
73 else{
74 rms_level = -9999;
77 db = 20*log10(max/32767.0);
78 if(db > -9999){
79 peak_level = db;
81 else{
82 peak_level = -9999;
88 char* sample_format_str(int format){
89 switch(format){
90 case AUDIO_S16: return "signed 16-bit LE";
91 case AUDIO_U16: return "unsigned 16-bit LE";
92 case AUDIO_S16MSB: return "signed 16-bit BE";
93 case AUDIO_U16MSB: return "unsigned 16-bit BE";
94 case AUDIO_S8: return "signed 8-bit";
95 case AUDIO_U8: return "unsigned 8-bit";
96 default: return "unknown";
100 void audio_init(){
101 SDL_AudioSpec want;
102 SDL_AudioSpec got;
105 want.freq = SAMPLE_RATE;
106 want.format = AUDIO_S16;
107 want.channels = 2;
108 want.samples = BUFFER_SIZE;
109 want.callback = audio_callback;
112 if(SDL_OpenAudio(&want, &got)<0){
113 fatal_error("sdl: cannot open audio (%s)\n", SDL_GetError());
116 printf("audio:\n");
117 printf(" sample rate: %d\n", got.freq);
118 printf(" channels: %d\n", got.channels);
119 printf(" samples: %d\n", got.samples);
120 printf(" format: %s\n", sample_format_str(got.format));
122 if(got.format != AUDIO_S16){
123 printf(" WARNING: audio format not AUDIO_S16 :(\n");
124 SDL_CloseAudio();
125 printf(" *no sound*\n");
126 return;
128 lout = xmalloc(got.samples*sizeof(float));
129 rout = xmalloc(got.samples*sizeof(float));
130 memset(lout, 0, got.samples*sizeof(float));
131 memset(rout, 0, got.samples*sizeof(float));
133 org_init();
134 synth_init();
135 seq_init();
137 printf(" sound online\n");
138 SDL_PauseAudio(0);
143 void audio_quit(){
144 SDL_CloseAudio();
145 free(lout);
146 free(rout);
149 int audio_peak_level(){
150 return peak_level;
153 int audio_rms_level(){
154 return rms_level;
158 void audio_lock(){
159 SDL_LockAudio();
162 void audio_unlock(){
163 SDL_UnlockAudio();