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