- further work on theme colors:
[blender.git] / source / blender / src / editsound.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include <stdio.h>
34 #include <math.h>
35 #include <string.h>
36 #include <fcntl.h>
37
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif
41
42 #ifndef WIN32 
43 #include <unistd.h>
44 #else
45 #include <io.h>
46 #endif
47 #include "MEM_guardedalloc.h"
48
49 #include "BLI_blenlib.h"
50 #include "BLI_arithb.h"
51
52 #include "DNA_object_types.h"
53 #include "DNA_screen_types.h"
54 #include "DNA_scene_types.h"
55 #include "DNA_sound_types.h"
56 #include "DNA_packedFile_types.h"
57
58 #include "BKE_utildefines.h"
59 #include "BKE_global.h"
60 #include "BKE_main.h"
61 #include "BKE_sound.h"
62 #include "BKE_library.h"
63 #include "BKE_packedFile.h"
64
65 #include "BIF_space.h"
66 #include "BIF_screen.h"
67 #include "BIF_interface.h"
68 #include "BIF_editsound.h"
69 #include "BIF_mywindow.h"
70
71 #include "BSE_drawipo.h"
72 #include "BSE_headerbuttons.h"
73
74 #include "blendef.h"
75
76 #include "mydevice.h"
77
78 #include "SND_C-api.h"
79 #include "SND_DependKludge.h"
80
81 #include "SYS_System.h"
82
83 /* this might move to the external header */
84 void* sound_get_libraryinterface(void);
85
86 static SND_SceneHandle ghSoundScene;
87 static SND_AudioDeviceInterfaceHandle ghAudioDeviceInterface;
88
89 /* que? why only here? because of the type define? */
90 bSound *sound_find_sound(char *id_name);
91 void sound_read_wav_data(bSound * sound, PackedFile * pf);
92 void sound_stop_sound(void *object, bSound *sound);
93 void winqreadsoundspace(struct ScrArea *sa, void *spacedata, struct BWinEvent *evt);
94 /*  void sound_stop_all_sounds(void); already in BIF_editsound.h */
95
96
97
98 /* Right. Now for some implementation: */
99 void winqreadsoundspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
100 {
101         SpaceSound *ssound= spacedata;
102         unsigned short event= evt->event;
103         short val= evt->val;
104         float dx, dy;
105         int doredraw= 0, cfra, first = 0;
106         short mval[2], nr;
107         
108         if(curarea->win==0) return;
109
110         if(val) {
111                 
112                 if( uiDoBlocks(&curarea->uiblocks, event)!=UI_NOTHING ) event= 0;
113
114                 switch(event) {
115                 case LEFTMOUSE:
116                         ssound->flag |= SND_CFRA_NUM;
117                         do {
118                                 getmouseco_areawin(mval);
119                                 areamouseco_to_ipoco(G.v2d, mval, &dx, &dy);
120                                 
121                                 cfra = (int)dx;
122                                 if(cfra< 1) cfra= 1;
123                                 
124                                 if( cfra!=CFRA || first )
125                                 {
126                                         first= 0;
127                                         CFRA= cfra;
128                                         update_for_newframe();
129                                         force_draw_plus(SPACE_VIEW3D);
130                                 }
131                         
132                         } while(get_mbut()&L_MOUSE);
133                         ssound->flag &= ~SND_CFRA_NUM;
134                         
135                         doredraw= 1;
136
137                         break;
138                 case MIDDLEMOUSE:
139                 case WHEELUPMOUSE:
140                 case WHEELDOWNMOUSE:
141                         view2dmove(event);      /* in drawipo.c */
142                         break;
143                 case RIGHTMOUSE:
144                         nr= pupmenu("Time value%t|Frames %x1|Seconds%x2");
145                         if (nr>0) {
146                                 if(nr==1) ssound->flag |= SND_DRAWFRAMES;
147                                 else ssound->flag &= ~SND_DRAWFRAMES;
148                                 doredraw= 1;
149                         }
150
151                         break;
152                 case PADPLUSKEY:
153                         dx= (float)(0.1154*(G.v2d->cur.xmax-G.v2d->cur.xmin));
154                         G.v2d->cur.xmin+= dx;
155                         G.v2d->cur.xmax-= dx;
156                         test_view2d(G.v2d, curarea->winx, curarea->winy);
157
158                         doredraw= 1;
159                         break;
160                 case PADMINUS:
161                         dx= (float)(0.15*(G.v2d->cur.xmax-G.v2d->cur.xmin));
162                         G.v2d->cur.xmin-= dx;
163                         G.v2d->cur.xmax+= dx;
164                         test_view2d(G.v2d, curarea->winx, curarea->winy);
165
166                         doredraw= 1;
167                         break;
168                 case HOMEKEY:
169                         do_sound_buttons(B_SOUNDHOME);
170                         break;
171                 }
172         }
173
174         if(doredraw)
175                 scrarea_queue_winredraw(curarea);
176 }
177
178
179
180 void sound_initialize_sounds(void)
181 {
182         bSound* sound;
183
184         /* clear the soundscene */
185         SND_RemoveAllSounds(ghSoundScene);
186         SND_RemoveAllSamples(ghSoundScene);
187
188         /* initialize sounds */
189         sound = G.main->sound.first;
190         while (sound)
191         {
192                 sound_sample_is_null(sound);
193                 sound = (bSound *) sound->id.next;
194         }
195 }
196
197
198
199 bSound* sound_make_copy(bSound* originalsound)
200 {
201         bSound* sound = NULL;
202         char name[160];
203         int len;
204         
205         /* only copy sounds that are sounds */
206         if (originalsound)
207         {
208                 /* do some name magic */
209                 strcpy(name, originalsound->name);
210                 len = strlen(name);
211                 while ((len > 0) && (name[len - 1] != '/') && (name[len - 1] != '\\'))
212                         len--;
213                 
214                 /* allocate the needed memory */
215                 sound = alloc_libblock(&G.main->sound, ID_SO, name + len);
216                 
217                 /* create a soundobject */
218                 sound->snd_sound = SND_CreateSound();
219
220                 /* set the samplename */
221                 strcpy(sound->name, name);
222                 SND_SetSampleName(sound->snd_sound, sound->name);
223
224                 /* add the new object to the soundscene */
225                 SND_AddSound(ghSoundScene, sound->snd_sound);
226                 
227                 /* and copy the data from the original */
228                 sound->attenuation = originalsound->attenuation;
229                 sound->distance = originalsound->distance;
230                 sound->max_gain = originalsound->max_gain;
231                 sound->min_gain = originalsound->min_gain;
232                 sound->newpackedfile = originalsound->newpackedfile;
233                 sound->panning = originalsound->panning;
234                 sound->pitch = originalsound->pitch;
235                 sound->sample = originalsound->sample;
236                 sound->volume = originalsound->volume;
237                 
238                 if (originalsound->flags & SOUND_FLAGS_3D)
239                         sound->flags |= SOUND_FLAGS_3D;
240                 else
241                         sound->flags &= ~SOUND_FLAGS_3D;
242         }
243         
244         return sound;
245 }
246
247
248
249 void sound_initialize_sample(bSound* sound)
250 {
251         if (sound && sound->sample == NULL)
252                 sound_sample_is_null(sound);
253 }
254
255
256 void sound_read_wav_data(bSound* sound, PackedFile* pf)
257 {
258         int i, temp;
259         short shortbuf, *temps;
260         int longbuf;
261         char buffer[25];
262         char *data = NULL;
263         char *tempc;
264         bSample *sample = NULL;
265         int channels, rate, bits, len;
266         
267         /* prepare for the worst... */
268         sound->sample->type = SAMPLE_INVALID;
269
270         rewindPackedFile(pf);
271
272         /* check to see if it is a file in "RIFF WAVE fmt" format */
273         if (readPackedFile(pf, buffer, 16) != 16)
274         {
275                 if (G.f & G_DEBUG) printf("File too short\n");
276                 return;
277         }
278
279         if(!(memcmp(buffer, "RIFF", 4) && memcmp(&(buffer[8]), "WAVEfmt ", 8)))
280         {
281                 readPackedFile(pf, &i, 4);// start of data
282                 if(G.order==B_ENDIAN)
283                         SWITCH_INT(i);
284
285                 /* read the sampleformat */
286                 readPackedFile(pf, &shortbuf, 2);
287                 if(G.order==B_ENDIAN)
288                 {
289                         /* was SWITCH_SHORT before */
290                         char s_i, *p_i;
291                         p_i= (char *)&(shortbuf);
292                         s_i= p_i[0];
293                         p_i[0]= p_i[1];
294                         p_i[1]= s_i;
295                 }
296
297                 /* read the number of channels */
298                 readPackedFile(pf, &shortbuf, 2);
299
300                 if(G.order==B_ENDIAN)
301                 {
302                         /* was SWITCH_SHORT before */
303                         char s_i, *p_i;
304                         p_i= (char *)&(shortbuf);
305                         s_i= p_i[0];
306                         p_i[0]= p_i[1];
307                         p_i[1]= s_i;
308                 }
309
310                 /* check the number of channels */
311                 if(shortbuf != 1 && shortbuf != 2)
312                 {
313                         if (G.f & G_DEBUG) printf("Unsupported number of channels\n");
314                         return;
315                 }
316                 channels = shortbuf;
317                 
318                 /* read the samplerate */
319                 readPackedFile(pf, &longbuf, 4);
320
321
322                 if(G.order==B_ENDIAN)
323                         SWITCH_INT(longbuf);
324                 rate = longbuf;
325                 
326                 /* read the bitrate */
327                 // Ton's way
328                 readPackedFile(pf, &temp, 4);
329
330                 if(G.order==B_ENDIAN)
331                         SWITCH_INT(temp);
332
333                 if(channels && rate)
334                         bits= 8*temp/(rate * channels);
335                 
336                 // Frank's way
337
338                 readPackedFile(pf, &shortbuf, 2);
339                 readPackedFile(pf, &shortbuf, 2);
340                 if(G.order==B_ENDIAN)
341                 {
342                         /* was SWITCH_SHORT before */
343                         char s_i, *p_i;
344                         p_i= (char *)&(shortbuf);
345                         s_i= p_i[0];
346                         p_i[0]= p_i[1];
347                         p_i[1]= s_i;
348                 }
349                 bits = shortbuf;
350                 
351                 seekPackedFile(pf, i-16, SEEK_CUR);
352                 readPackedFile(pf, buffer, 4);
353                 /* check if we have a 'data' chunk */
354                 while(memcmp(buffer, "data", 4)!=0)
355                 {
356                         if (readPackedFile(pf, &i, 4) != 4)
357                                 break;
358                         
359                         if(G.order==B_ENDIAN)
360                                 SWITCH_INT(i);
361
362                         seekPackedFile(pf, i, SEEK_CUR);
363                         if (readPackedFile(pf, buffer, 4) != 4)
364                                 break;
365                 }
366                 
367                 /* guess not */
368                 if (memcmp(buffer, "data", 4) !=0)
369                 {
370                         if (G.f & G_DEBUG) printf("No data found\n");
371                 }
372                 /* or maybe we do! */
373                 else
374                 {
375                         readPackedFile(pf, &longbuf, 4); 
376                         if(G.order==B_ENDIAN) SWITCH_INT(longbuf);
377                         
378                         /* handle 8 and 16 bit samples differently */
379                         /* intrr: removed, longbuf is length in bytes, not samples */
380                         if (bits == 16)
381                                 data = (char *)MEM_mallocN(longbuf, "sample data");
382                         else 
383                                 data = (char *)MEM_mallocN(longbuf*2, "sample data");
384
385                         len = longbuf /*/ 4.0*/; /* for some strange reason the sample length is off by a factor of 4... */
386                         /* intrr's comment: Funny eh, how one 16-bit stereo sample is 4 bytes? :-) */
387                         
388                         if(data)
389                         {
390                                 readPackedFile(pf, data, len);
391                                 /* data is only used to draw! */
392                                 if (bits == 8)
393                                 {
394                                         temps = (short *) data;
395                                         tempc = (char *) data;
396                                         for (i = len - 1; i >= 0; i--)
397                                                 temps[i] = tempc[i] << 8;
398                                 }
399                                 else
400                                 {
401                                         if(G.order==B_ENDIAN)
402                                         {
403                                                 swab(data, data, len);
404                                         }
405                                 }
406                                 /* fill the sound with the found data */
407                                 sample = sound->sample;
408                                 sample->channels = channels;
409                                 sample->rate = rate;
410                                 sample->bits = bits;
411                                 sample->len = len;
412                                 sample->data = data;
413                                 sample->type = SAMPLE_WAV;
414                         }
415                 }
416         }
417         else
418         {
419                 sound->sample->type = SAMPLE_INVALID;
420                 if (G.f & G_DEBUG) printf("Unsupported sound format: %s\n", sound->name);
421         }
422 }
423
424
425
426 /* ugly, but it works (for now) */
427 int sound_get_filetype_from_header(bSound* sound, PackedFile* pf)
428 {
429         int filetype = SAMPLE_INVALID;
430         int i;
431         char buffer[25];
432         short shortbuf;
433         
434         rewindPackedFile(pf);
435         
436         if (readPackedFile(pf, buffer, 16) != 16)
437         {
438                 if (G.f & G_DEBUG) printf("File too short\n");
439                 return filetype;
440         }
441         
442         if(!(memcmp(buffer, "RIFF", 4) && memcmp(&(buffer[8]), "WAVEfmt ", 8)))
443         {
444                 readPackedFile(pf, &i, 4);
445                 if(G.order==B_ENDIAN)
446                         SWITCH_INT(i);
447                 
448                 /* read the sampleformat */
449                 readPackedFile(pf, &shortbuf, 2);
450                 if(G.order==B_ENDIAN)
451                 {
452                         char s_i, *p_i;
453                         p_i= (char *)&(shortbuf);
454                         s_i= p_i[0];
455                         p_i[0]= p_i[1];
456                         p_i[1]= s_i;
457                 }
458                 
459                 if (shortbuf == SND_WAVE_FORMAT_PCM)
460                 {
461                         filetype = SAMPLE_WAV;
462                 }
463                 else
464                         /* only fmod supports compressed wav */
465 #ifdef USE_FMOD
466                 {
467                         /* and only valid publishers may use compressed wav */
468                         switch (shortbuf)
469                         {
470                         case SND_WAVE_FORMAT_ADPCM:
471                         case SND_WAVE_FORMAT_ALAW:
472                         case SND_WAVE_FORMAT_MULAW:
473                         case SND_WAVE_FORMAT_DIALOGIC_OKI_ADPCM:
474                         case SND_WAVE_FORMAT_CONTROL_RES_VQLPC:
475                         case SND_WAVE_FORMAT_GSM_610:
476                         case SND_WAVE_FORMAT_MPEG3:
477                                 filetype = SAMPLE_WAV;
478                                 break;
479                         default:
480 #endif
481                                 {
482                                         filetype = SAMPLE_INVALID;
483                                         if (G.f & G_DEBUG) printf("Unsupported wav compression\n");
484                                 }
485                         }
486 #ifdef USE_FMOD
487                 }
488         }
489         else if (!memcmp(buffer, "OggS", 4))
490         {
491                 filetype = SAMPLE_OGG_VORBIS;
492         }
493         else if ((!memcmp(buffer, "ID3", 3)) || (!memcmp(buffer, "ÿû", 2)))
494         {
495                 filetype = SAMPLE_MP3;
496         }
497 #endif
498         else
499         {
500                 filetype = SAMPLE_INVALID;
501                 if (G.f & G_DEBUG) printf("Unsupported sound format: %s\n", sound->name);
502         }
503         
504         return filetype;
505 }
506
507
508
509 int check_filetype(bSound* sound, PackedFile* pf)
510 {
511 //      char* pdest;
512         sound->sample->type = SAMPLE_INVALID;
513 /*      
514         // parse the name for the extension to see what kind of sample it is
515         pdest = strrchr(sound->sample->name, '.');
516
517         // a simple check to see what kind of sample we're dealing with
518         if (stricmp(pdest, ".wav") == 0)
519                 sound->sample->type = SAMPLE_WAV;
520
521 #ifdef USE_FMOD
522         if (stricmp(pdest, ".mp2") == 0)
523                 sound->sample->type = SAMPLE_MP2;
524         if (stricmp(pdest, ".mp3") == 0)
525                 sound->sample->type = SAMPLE_MP3;
526         if (stricmp(pdest, ".ogg") == 0)
527                 sound->sample->type = SAMPLE_OGG_VORBIS;
528         if (stricmp(pdest, ".raw") == 0)
529                 sound->sample->type = SAMPLE_RAW;
530         if (stricmp(pdest, ".wma") == 0)
531                 sound->sample->type = SAMPLE_WMA;
532         if (stricmp(pdest, ".asf") == 0)
533                 sound->sample->type = SAMPLE_ASF;
534 #endif
535 */
536         sound->sample->type = sound_get_filetype_from_header(sound, pf);
537
538         /* get some info from the sample */
539         switch (sound->sample->type)
540         {
541         case SAMPLE_WAV:
542                 {
543                         sound_read_wav_data(sound, pf);
544                         break;
545                 }
546         case SAMPLE_OGG_VORBIS:
547         case SAMPLE_MP3:
548         case SAMPLE_MP2:
549         case SAMPLE_RAW:
550         case SAMPLE_WMA:
551         case SAMPLE_ASF:
552                 break;
553         default:
554                 {
555                         if (G.f & G_DEBUG) printf("No valid sample: %s\n", sound->name);
556                         break;
557                 }
558         }
559         
560         return sound->sample->type;
561 }
562
563
564
565 int sound_load_sample(bSound* sound)
566 {
567         int result = FALSE;
568         PackedFile* pf;
569         int freePF = FALSE;
570         int buffer = -1;
571
572         /* check the sample (valid?) */
573         if (sound->sample->type == SAMPLE_UNKNOWN || sound->snd_sound == NULL)
574         {
575                 /* find... */
576                 pf = sound_find_packedfile(sound);
577
578                 /* ...or create a (temp)packedfile */
579                 if (pf == NULL)
580                 {
581                         pf = newPackedFile(sound->name);
582                         
583                         /* if autopack is off, free the pf afterwards */
584                         if ((G.fileflags & G_AUTOPACK) == 0)
585                                 freePF = TRUE;
586                 }
587                 
588                 /* if we have a valid pf... */
589                 if (pf)
590                 {
591                         /* check the content of the pf */
592                         check_filetype(sound, pf);
593
594                         /* check if the sampletype is supported */
595                         if (sound->sample->type != SAMPLE_INVALID && sound->sample->type != SAMPLE_UNKNOWN)
596                         {
597                                 /* register the sample at the audiodevice */
598                                 buffer = SND_AddSample(ghSoundScene, sound->sample->name, pf->data, pf->size);
599
600                                 /* create a soundobject */
601                                 sound->snd_sound = SND_CreateSound();
602                                 SND_SetSampleName(sound->snd_sound, sound->sample->name);
603                                         
604                                 /* add the soundobject to the soundscene  */
605                                 if (SND_CheckBuffer(ghSoundScene, sound->snd_sound))
606                                         SND_AddSound(ghSoundScene, sound->snd_sound);
607                                 else
608                                         if (G.f & G_DEBUG) printf("error: sample didn't load properly\n");
609                                 
610                                 /* if it was places in buffer[0] or higher, it succeeded */
611                                 if (buffer >= 0)
612                                         result = TRUE;
613                         }
614                         /* if not, free the pf */
615                         else
616                         {
617                                 freePF = TRUE;
618                         }
619                         
620                         /* if you want it freed, make it so */
621                         if (freePF)
622                         {
623                                 freePackedFile(pf);
624                                 pf = NULL;
625                         } 
626                         /* or else connect the pf to the sound and sample */
627 //                      else
628 //                      {
629                                 sound->newpackedfile = pf;
630                                 sound->sample->packedfile = pf;
631 //                      }
632                 }
633                 else 
634                 {
635                         if (G.f & G_DEBUG) printf("%s: File not found!\n", sound->name);
636                         sound->sample->type = SAMPLE_INVALID;
637                 }
638         }
639         /* if the sample ain't invalid, we're ready to go! */
640         else if (sound->sample->type != SAMPLE_INVALID)
641         {
642                 result = TRUE;
643         }
644
645         return result;
646 }
647
648
649
650 bSound* sound_new_sound(char* name)
651 {
652         bSound *sound = NULL;
653         int len, file;
654         char str[FILE_MAXDIR+FILE_MAXFILE];
655
656         if (!G.scene->audio.mixrate) G.scene->audio.mixrate = 44100;
657         /* convert the name to absolute path */
658         strcpy(str, name);
659         BLI_convertstringcode(str, G.sce, G.scene->r.cfra);
660
661         /* check if the sample on disk can be opened */
662         file = open(str, O_BINARY|O_RDONLY);
663         
664         if (file != -1)
665         {
666                 close(file);
667
668
669                 /* do some name magic */
670                 len = strlen(name);
671                 while (len > 0 && name[len - 1] != '/' && name[len - 1] != '\\')
672                         len--;
673                 
674                 /* allocate some memory for the sound */
675                 sound = alloc_libblock(&G.main->sound, ID_SO, name + len);
676                 strcpy(sound->name, name);
677                 
678                 /* intialize and check the sample */
679                 sound_initialize_sample(sound);
680
681                 /* load the sample & check if this blender supports the sound format */
682 //              sound_load_sample(sound);
683
684                 if (sound->sample->type == SAMPLE_INVALID)
685                 {
686                         free_libblock(&G.main->sound, sound);
687                         sound = NULL;
688                 } 
689                 else
690                 {
691                         sound->volume = 1.0;
692                         sound->attenuation = 1.0;
693                         sound->distance = 1.0;
694                         sound->min_gain = 0.0;
695                         sound->max_gain = 1.0;
696                 }
697         }
698         
699         return (sound);
700 }
701
702
703
704 int sound_set_sample(bSound *sound, bSample *sample)
705 {
706         int result = TRUE;
707         /* decrease the usernumber for this sample */
708         if (sound->sample)
709                 sound->sample->id.us--;
710
711         /* delete the soundobject */
712         if (sound->snd_sound)
713         {
714                 SND_RemoveSound(ghSoundScene, sound->snd_sound);
715                 sound->snd_sound = NULL;
716         }
717
718         /* connect the sample to the sound */
719         sound->sample = sample;
720         sound->newpackedfile = NULL;
721         
722         /* increase the usercount */
723         if (sound->sample)
724         {
725                 sound->sample->id.us++;
726
727                 /* and set the right pf */
728                 sound->newpackedfile = sample->packedfile;
729
730                 /* if the sampletype is unknown initialize it */
731                 if (sound->sample->type == SAMPLE_UNKNOWN)
732                 {
733                         sound_initialize_sample(sound);
734                         
735                         /* load the sample & check if this blender supports the sound format */
736                         if (!sound_load_sample(sound))
737                         {
738                                 result = FALSE;
739                         }
740                 }
741         }
742
743         return result;
744 }
745
746
747
748 bSample *sound_new_sample(bSound * sound)
749 {
750         bSample *sample = NULL;
751         int len;
752         char *name;
753         
754         if (sound != NULL)
755         {
756                 name = sound->name;     
757                 len = strlen(name);
758                 /* do some name magic */
759                 while (len > 0 && name[len - 1] != '/' && name[len - 1] != '\\')
760                         len--;
761                 
762                 /* allocate the memory for the sample */
763                 sample = alloc_libblock(samples, ID_SAMPLE, name + len);
764                 sample->data = &sample->fakedata[0];
765                 sample->type = SAMPLE_UNKNOWN;
766                 
767                 /* some default settings. We get divide by zero if these values are not set     */
768                 sample->channels = 1;
769                 sample->rate = 44100;
770                 sample->bits = 16;
771                 sample->alindex = SAMPLE_INVALID;
772
773                 /* convert sound->name to abolute filename */
774                 strcpy(sample->name, sound->name);
775                 BLI_convertstringcode(sample->name, G.sce, G.scene->r.cfra);
776                 
777                 /* connect the pf to the sample */
778                 if (sound->newpackedfile)
779                         sample->packedfile = sound->newpackedfile;
780                 else
781                         sample->packedfile = sound_find_packedfile(sound);
782         }
783         
784         return(sample);
785 }
786
787
788
789 /* find a sample that might already be loaded */
790 bSample* sound_find_sample(bSound* sound)
791 {
792         bSample* sample;
793         char name[FILE_MAXDIR + FILE_MAXFILE];
794         char samplename[FILE_MAXDIR + FILE_MAXFILE];
795         
796         // convert sound->name to abolute filename
797         strcpy(name, sound->name);
798         BLI_convertstringcode(name, G.sce, G.scene->r.cfra);
799         
800         /* search through the list of loaded samples */
801         sample = samples->first;
802         
803         while (sample)
804         {
805                 strcpy(samplename, sample->name);
806                 BLI_convertstringcode(samplename, G.sce, G.scene->r.cfra);
807                 
808                 if (strcmp(name, samplename) == 0)
809                 {
810                         break;
811                 }
812                 sample = sample->id.next;
813         }
814         
815         return (sample);
816 }
817
818
819
820 int sound_sample_is_null(bSound* sound)
821 {
822         int result = FALSE;
823         bSample* sample;
824         
825         /* find the right sample or else create one */
826         if (sound->sample == NULL)
827         {
828                 /* find... */
829                 sample = sound_find_sample(sound);
830
831                 /* or a new one? */
832                 if (sample == NULL)
833                         sample = sound_new_sample(sound);
834                 
835                 if (sound_set_sample(sound, sample))
836                         result = TRUE;
837         }
838
839         return result;
840 }
841
842
843
844 void sound_stop_all_sounds(void)
845 {
846 #if GAMEBLENDER == 1
847         SND_StopAllSounds(ghSoundScene);
848         SND_Proceed(ghAudioDeviceInterface, ghSoundScene);
849 #endif 
850 }
851
852
853
854 void sound_end_all_sounds(void)
855 {
856 #if GAMEBLENDER == 1
857         sound_stop_all_sounds();
858         SND_RemoveAllSounds(ghSoundScene);
859 #endif
860 }
861
862
863
864 void sound_play_sound(bSound* sound)
865 {
866 #if GAMEBLENDER == 1
867         /* first check if we want sound or not */
868         SND_IsPlaybackWanted(ghSoundScene);
869
870         /* stop all previous sounds */
871         SND_StopAllSounds(ghSoundScene);
872         
873         if (sound != NULL && sound->sample != NULL)
874         {
875                 /* load the sample if needed */
876                 if (sound_load_sample(sound))
877                 {
878                         /* set all kinds of parameters */
879                         SND_SetListenerGain(ghSoundScene, G.listener->gain);
880                         SND_SetDopplerFactor(ghSoundScene, G.listener->dopplerfactor);
881                         SND_SetDopplerVelocity(ghSoundScene, G.listener->dopplervelocity);
882                         
883                         SND_SetGain((SND_ObjectHandle)sound->snd_sound, (sound->volume));
884                         SND_SetPitch((SND_ObjectHandle)sound->snd_sound, (exp((sound->pitch / 12.0) * log(2.0))));
885                         
886                         if (sound->flags & SOUND_FLAGS_LOOP)
887                         {
888                                 SND_SetLoopMode((SND_ObjectHandle)sound->snd_sound, SND_LOOP_NORMAL);
889 #ifdef SOUND_UNDER_DEVELOPMENT
890 /*                              SND_SetLoopPoints((SND_ObjectHandle)sound->snd_sound, sound->loopstart, sound->loopend);
891 */
892 #endif
893                                 if (sound->flags & SOUND_FLAGS_BIDIRECTIONAL_LOOP)
894                                         SND_SetLoopMode((SND_ObjectHandle)sound->snd_sound, SND_LOOP_BIDIRECTIONAL);
895                                 else
896                                         SND_SetLoopMode((SND_ObjectHandle)sound->snd_sound, SND_LOOP_NORMAL);
897
898                         }
899                         else 
900                         {
901                                 SND_SetLoopMode((SND_ObjectHandle)sound->snd_sound, SND_LOOP_OFF);
902                         }
903                         
904                         if (sound->flags & SOUND_FLAGS_3D)
905                         {
906                                 SND_SetRollOffFactor((SND_ObjectHandle)sound->snd_sound, sound->attenuation);
907                                 SND_SetReferenceDistance((SND_ObjectHandle)sound->snd_sound, sound->distance);
908                                 SND_SetMinimumGain((SND_ObjectHandle)sound->snd_sound, sound->min_gain);
909                                 SND_SetMaximumGain((SND_ObjectHandle)sound->snd_sound, sound->max_gain);
910                         }
911                         else
912                         {
913                                 SND_SetRollOffFactor((SND_ObjectHandle)sound->snd_sound, 0);
914                                 SND_SetReferenceDistance((SND_ObjectHandle)sound->snd_sound, 1);
915                                 SND_SetMinimumGain((SND_ObjectHandle)sound->snd_sound, 1);
916                                 SND_SetMaximumGain((SND_ObjectHandle)sound->snd_sound, 1);
917                         }
918                         
919                         if (G.f & G_DEBUG) printf("Set pitch to: %f\n", SND_GetPitch((SND_ObjectHandle)sound->snd_sound));
920                         if (G.f & G_DEBUG) printf("Set gain to: %f\n", SND_GetGain((SND_ObjectHandle)sound->snd_sound));
921                         if (G.f & G_DEBUG) printf("Set looping to: %d\n", SND_GetLoopMode((SND_ObjectHandle)sound->snd_sound));
922                         
923                         /* play the sound */
924                         SND_StartSound(ghSoundScene, (SND_ObjectHandle)sound->snd_sound);
925
926                         /* update the device */
927                         SND_Proceed(ghAudioDeviceInterface, ghSoundScene);
928                 }
929         }
930         else 
931         {
932                 if (G.f & G_DEBUG)
933                 {
934                         printf("uninitialized sound !\n");              
935                         if (sound)
936                         {
937                                 printf("sound: %p\n", sound);
938                                 if (sound->sample)
939                                 {
940                                         printf("sample: %p\n", sound->sample);
941                                         if (sound->snd_sound)
942                                                 printf("hSoundObject: %p\n", sound->snd_sound);
943                                 }
944                         }
945                         else
946                         {
947                                 printf("sound == NULL\n");
948                         }
949                 }
950         }
951 #endif 
952 }
953
954
955
956 bSound *sound_find_sound(char *id_name)
957 {
958         bSound *sound;
959         
960         // look for sound with same *id* name
961         sound = G.main->sound.first;
962         while (sound)
963         {
964                 if (strcmp(sound->id.name + 2, id_name) == 0)
965                         break;
966
967                 sound = sound->id.next;
968         }
969         
970         return sound;
971 }
972
973
974
975 static void sound_init_listener(void)
976 {
977         G.listener = MEM_callocN(sizeof(bSoundListener), "soundlistener");
978         G.listener->gain = 1.0;
979         G.listener->dopplerfactor = 1.0;
980         G.listener->dopplervelocity = 1.0;
981 }
982
983
984
985 void sound_init_audio(void)
986 {
987         int noaudio;
988         SYS_SystemHandle hSystem = NULL;
989         ghAudioDeviceInterface = NULL;
990         
991         hSystem = SYS_GetSystem();
992         noaudio = SYS_GetCommandLineInt(hSystem,"noaudio",0);
993         
994         if (1)/*(noaudio) intrr: disable game engine audio (openal) */
995                 SND_SetDeviceType(snd_e_dummydevice);
996
997         ghAudioDeviceInterface = SND_GetAudioDevice();
998         ghSoundScene = SND_CreateScene(ghAudioDeviceInterface);
999
1000         sound_init_listener();
1001 }
1002
1003
1004
1005 int sound_get_mixrate(void)
1006 {
1007         return MIXRATE;
1008 }
1009
1010
1011
1012 static void sound_exit_listener(void)
1013 {
1014         MEM_freeN(G.listener);
1015 }
1016
1017
1018
1019 void sound_exit_audio(void)
1020 {
1021         SND_DeleteScene(ghSoundScene);
1022         SND_ReleaseDevice();
1023         sound_exit_listener();
1024 }