Fix for slow starting of Blender.
[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=NULL;
87 static SND_AudioDeviceInterfaceHandle ghAudioDeviceInterface=NULL;
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         if(ghSoundScene) {
185
186                 /* clear the soundscene */
187                 SND_RemoveAllSounds(ghSoundScene);
188                 SND_RemoveAllSamples(ghSoundScene);
189         
190                 /* initialize sounds */
191                 sound = G.main->sound.first;
192                 while (sound)
193                 {
194                         sound_sample_is_null(sound);
195                         sound = (bSound *) sound->id.next;
196                 }
197         }
198 }
199
200
201
202 bSound* sound_make_copy(bSound* originalsound)
203 {
204         bSound* sound = NULL;
205         char name[160];
206         int len;
207         
208         if(ghSoundScene==NULL) sound_init_audio();
209         
210         /* only copy sounds that are sounds */
211         if (originalsound)
212         {
213                 /* do some name magic */
214                 strcpy(name, originalsound->name);
215                 len = strlen(name);
216                 while ((len > 0) && (name[len - 1] != '/') && (name[len - 1] != '\\'))
217                         len--;
218                 
219                 /* allocate the needed memory */
220                 sound = alloc_libblock(&G.main->sound, ID_SO, name + len);
221                 
222                 /* create a soundobject */
223                 sound->snd_sound = SND_CreateSound();
224
225                 /* set the samplename */
226                 strcpy(sound->name, name);
227                 SND_SetSampleName(sound->snd_sound, sound->name);
228
229                 /* add the new object to the soundscene */
230                 SND_AddSound(ghSoundScene, sound->snd_sound);
231                 
232                 /* and copy the data from the original */
233                 sound->attenuation = originalsound->attenuation;
234                 sound->distance = originalsound->distance;
235                 sound->max_gain = originalsound->max_gain;
236                 sound->min_gain = originalsound->min_gain;
237                 sound->newpackedfile = originalsound->newpackedfile;
238                 sound->panning = originalsound->panning;
239                 sound->pitch = originalsound->pitch;
240                 sound->sample = originalsound->sample;
241                 sound->volume = originalsound->volume;
242                 
243                 if (originalsound->flags & SOUND_FLAGS_3D)
244                         sound->flags |= SOUND_FLAGS_3D;
245                 else
246                         sound->flags &= ~SOUND_FLAGS_3D;
247         }
248         
249         return sound;
250 }
251
252
253
254 void sound_initialize_sample(bSound* sound)
255 {
256         if(ghSoundScene==NULL) sound_init_audio();
257
258         if (sound && sound->sample == NULL)
259                 sound_sample_is_null(sound);
260 }
261
262
263 void sound_read_wav_data(bSound* sound, PackedFile* pf)
264 {
265         int i, temp;
266         short shortbuf, *temps;
267         int longbuf;
268         char buffer[25];
269         char *data = NULL;
270         char *tempc;
271         bSample *sample = NULL;
272         int channels, rate, bits, len;
273         
274         /* prepare for the worst... */
275         sound->sample->type = SAMPLE_INVALID;
276
277         rewindPackedFile(pf);
278
279         /* check to see if it is a file in "RIFF WAVE fmt" format */
280         if (readPackedFile(pf, buffer, 16) != 16)
281         {
282                 if (G.f & G_DEBUG) printf("File too short\n");
283                 return;
284         }
285
286         if(!(memcmp(buffer, "RIFF", 4) && memcmp(&(buffer[8]), "WAVEfmt ", 8)))
287         {
288                 readPackedFile(pf, &i, 4);// start of data
289                 if(G.order==B_ENDIAN)
290                         SWITCH_INT(i);
291
292                 /* read the sampleformat */
293                 readPackedFile(pf, &shortbuf, 2);
294                 if(G.order==B_ENDIAN)
295                 {
296                         /* was SWITCH_SHORT before */
297                         char s_i, *p_i;
298                         p_i= (char *)&(shortbuf);
299                         s_i= p_i[0];
300                         p_i[0]= p_i[1];
301                         p_i[1]= s_i;
302                 }
303
304                 /* read the number of channels */
305                 readPackedFile(pf, &shortbuf, 2);
306
307                 if(G.order==B_ENDIAN)
308                 {
309                         /* was SWITCH_SHORT before */
310                         char s_i, *p_i;
311                         p_i= (char *)&(shortbuf);
312                         s_i= p_i[0];
313                         p_i[0]= p_i[1];
314                         p_i[1]= s_i;
315                 }
316
317                 /* check the number of channels */
318                 if(shortbuf != 1 && shortbuf != 2)
319                 {
320                         if (G.f & G_DEBUG) printf("Unsupported number of channels\n");
321                         return;
322                 }
323                 channels = shortbuf;
324                 
325                 /* read the samplerate */
326                 readPackedFile(pf, &longbuf, 4);
327
328
329                 if(G.order==B_ENDIAN)
330                         SWITCH_INT(longbuf);
331                 rate = longbuf;
332                 
333                 /* read the bitrate */
334                 // Ton's way
335                 readPackedFile(pf, &temp, 4);
336
337                 if(G.order==B_ENDIAN)
338                         SWITCH_INT(temp);
339
340                 if(channels && rate)
341                         bits= 8*temp/(rate * channels);
342                 
343                 // Frank's way
344
345                 readPackedFile(pf, &shortbuf, 2);
346                 readPackedFile(pf, &shortbuf, 2);
347                 if(G.order==B_ENDIAN)
348                 {
349                         /* was SWITCH_SHORT before */
350                         char s_i, *p_i;
351                         p_i= (char *)&(shortbuf);
352                         s_i= p_i[0];
353                         p_i[0]= p_i[1];
354                         p_i[1]= s_i;
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                 {
363                         if (readPackedFile(pf, &i, 4) != 4)
364                                 break;
365                         
366                         if(G.order==B_ENDIAN)
367                                 SWITCH_INT(i);
368
369                         seekPackedFile(pf, i, SEEK_CUR);
370                         if (readPackedFile(pf, buffer, 4) != 4)
371                                 break;
372                 }
373                 
374                 /* guess not */
375                 if (memcmp(buffer, "data", 4) !=0)
376                 {
377                         if (G.f & G_DEBUG) printf("No data found\n");
378                 }
379                 /* or maybe we do! */
380                 else
381                 {
382                         readPackedFile(pf, &longbuf, 4); 
383                         if(G.order==B_ENDIAN) SWITCH_INT(longbuf);
384                         
385                         /* handle 8 and 16 bit samples differently */
386                         /* intrr: removed, longbuf is length in bytes, not samples */
387                         if (bits == 16)
388                                 data = (char *)MEM_mallocN(longbuf, "sample data");
389                         else 
390                                 data = (char *)MEM_mallocN(longbuf*2, "sample data");
391
392                         len = longbuf /*/ 4.0*/; /* for some strange reason the sample length is off by a factor of 4... */
393                         /* intrr's comment: Funny eh, how one 16-bit stereo sample is 4 bytes? :-) */
394                         
395                         if(data)
396                         {
397                                 readPackedFile(pf, data, len);
398                                 /* data is only used to draw! */
399                                 if (bits == 8)
400                                 {
401                                         temps = (short *) data;
402                                         tempc = (char *) data;
403                                         for (i = len - 1; i >= 0; i--)
404                                                 temps[i] = tempc[i] << 8;
405                                 }
406                                 else
407                                 {
408                                         if(G.order==B_ENDIAN)
409                                         {
410                                                 swab(data, data, len);
411                                         }
412                                 }
413                                 /* fill the sound with the found data */
414                                 sample = sound->sample;
415                                 sample->channels = channels;
416                                 sample->rate = rate;
417                                 sample->bits = bits;
418                                 sample->len = len;
419                                 sample->data = data;
420                                 sample->type = SAMPLE_WAV;
421                         }
422                 }
423         }
424         else
425         {
426                 sound->sample->type = SAMPLE_INVALID;
427                 if (G.f & G_DEBUG) printf("Unsupported sound format: %s\n", sound->name);
428         }
429 }
430
431
432
433 /* ugly, but it works (for now) */
434 int sound_get_filetype_from_header(bSound* sound, PackedFile* pf)
435 {
436         int filetype = SAMPLE_INVALID;
437         int i;
438         char buffer[25];
439         short shortbuf;
440         
441         rewindPackedFile(pf);
442         
443         if (readPackedFile(pf, buffer, 16) != 16)
444         {
445                 if (G.f & G_DEBUG) printf("File too short\n");
446                 return filetype;
447         }
448         
449         if(!(memcmp(buffer, "RIFF", 4) && memcmp(&(buffer[8]), "WAVEfmt ", 8)))
450         {
451                 readPackedFile(pf, &i, 4);
452                 if(G.order==B_ENDIAN)
453                         SWITCH_INT(i);
454                 
455                 /* read the sampleformat */
456                 readPackedFile(pf, &shortbuf, 2);
457                 if(G.order==B_ENDIAN)
458                 {
459                         char s_i, *p_i;
460                         p_i= (char *)&(shortbuf);
461                         s_i= p_i[0];
462                         p_i[0]= p_i[1];
463                         p_i[1]= s_i;
464                 }
465                 
466                 if (shortbuf == SND_WAVE_FORMAT_PCM)
467                 {
468                         filetype = SAMPLE_WAV;
469                 }
470                 else
471                         /* only fmod supports compressed wav */
472 #ifdef USE_FMOD
473                 {
474                         /* and only valid publishers may use compressed wav */
475                         switch (shortbuf)
476                         {
477                         case SND_WAVE_FORMAT_ADPCM:
478                         case SND_WAVE_FORMAT_ALAW:
479                         case SND_WAVE_FORMAT_MULAW:
480                         case SND_WAVE_FORMAT_DIALOGIC_OKI_ADPCM:
481                         case SND_WAVE_FORMAT_CONTROL_RES_VQLPC:
482                         case SND_WAVE_FORMAT_GSM_610:
483                         case SND_WAVE_FORMAT_MPEG3:
484                                 filetype = SAMPLE_WAV;
485                                 break;
486                         default:
487 #endif
488                                 {
489                                         filetype = SAMPLE_INVALID;
490                                         if (G.f & G_DEBUG) printf("Unsupported wav compression\n");
491                                 }
492                         }
493 #ifdef USE_FMOD
494                 }
495         }
496         else if (!memcmp(buffer, "OggS", 4))
497         {
498                 filetype = SAMPLE_OGG_VORBIS;
499         }
500         else if ((!memcmp(buffer, "ID3", 3)) || (!memcmp(buffer, "ÿû", 2)))
501         {
502                 filetype = SAMPLE_MP3;
503         }
504 #endif
505         else
506         {
507                 filetype = SAMPLE_INVALID;
508                 if (G.f & G_DEBUG) printf("Unsupported sound format: %s\n", sound->name);
509         }
510         
511         return filetype;
512 }
513
514
515
516 int check_filetype(bSound* sound, PackedFile* pf)
517 {
518 //      char* pdest;
519         sound->sample->type = SAMPLE_INVALID;
520 /*      
521         // parse the name for the extension to see what kind of sample it is
522         pdest = strrchr(sound->sample->name, '.');
523
524         // a simple check to see what kind of sample we're dealing with
525         if (stricmp(pdest, ".wav") == 0)
526                 sound->sample->type = SAMPLE_WAV;
527
528 #ifdef USE_FMOD
529         if (stricmp(pdest, ".mp2") == 0)
530                 sound->sample->type = SAMPLE_MP2;
531         if (stricmp(pdest, ".mp3") == 0)
532                 sound->sample->type = SAMPLE_MP3;
533         if (stricmp(pdest, ".ogg") == 0)
534                 sound->sample->type = SAMPLE_OGG_VORBIS;
535         if (stricmp(pdest, ".raw") == 0)
536                 sound->sample->type = SAMPLE_RAW;
537         if (stricmp(pdest, ".wma") == 0)
538                 sound->sample->type = SAMPLE_WMA;
539         if (stricmp(pdest, ".asf") == 0)
540                 sound->sample->type = SAMPLE_ASF;
541 #endif
542 */
543         sound->sample->type = sound_get_filetype_from_header(sound, pf);
544
545         /* get some info from the sample */
546         switch (sound->sample->type)
547         {
548         case SAMPLE_WAV:
549                 {
550                         sound_read_wav_data(sound, pf);
551                         break;
552                 }
553         case SAMPLE_OGG_VORBIS:
554         case SAMPLE_MP3:
555         case SAMPLE_MP2:
556         case SAMPLE_RAW:
557         case SAMPLE_WMA:
558         case SAMPLE_ASF:
559                 break;
560         default:
561                 {
562                         if (G.f & G_DEBUG) printf("No valid sample: %s\n", sound->name);
563                         break;
564                 }
565         }
566         
567         return sound->sample->type;
568 }
569
570
571
572 int sound_load_sample(bSound* sound)
573 {
574         int result = FALSE;
575         PackedFile* pf;
576         int freePF = FALSE;
577         int buffer = -1;
578
579         if(ghSoundScene==NULL) sound_init_audio();
580
581         /* check the sample (valid?) */
582         if (sound->sample->type == SAMPLE_UNKNOWN || sound->snd_sound == NULL)
583         {
584                 /* find... */
585                 pf = sound_find_packedfile(sound);
586
587                 /* ...or create a (temp)packedfile */
588                 if (pf == NULL)
589                 {
590                         pf = newPackedFile(sound->name);
591                         
592                         /* if autopack is off, free the pf afterwards */
593                         if ((G.fileflags & G_AUTOPACK) == 0)
594                                 freePF = TRUE;
595                 }
596                 
597                 /* if we have a valid pf... */
598                 if (pf)
599                 {
600                         /* check the content of the pf */
601                         check_filetype(sound, pf);
602
603                         /* check if the sampletype is supported */
604                         if (sound->sample->type != SAMPLE_INVALID && sound->sample->type != SAMPLE_UNKNOWN)
605                         {
606                                 /* register the sample at the audiodevice */
607                                 buffer = SND_AddSample(ghSoundScene, sound->sample->name, pf->data, pf->size);
608
609                                 /* create a soundobject */
610                                 sound->snd_sound = SND_CreateSound();
611                                 SND_SetSampleName(sound->snd_sound, sound->sample->name);
612                                         
613                                 /* add the soundobject to the soundscene  */
614                                 if (SND_CheckBuffer(ghSoundScene, sound->snd_sound))
615                                         SND_AddSound(ghSoundScene, sound->snd_sound);
616                                 else
617                                         if (G.f & G_DEBUG) printf("error: sample didn't load properly\n");
618                                 
619                                 /* if it was places in buffer[0] or higher, it succeeded */
620                                 if (buffer >= 0)
621                                         result = TRUE;
622                         }
623                         /* if not, free the pf */
624                         else
625                         {
626                                 freePF = TRUE;
627                         }
628                         
629                         /* if you want it freed, make it so */
630                         if (freePF)
631                         {
632                                 freePackedFile(pf);
633                                 pf = NULL;
634                         } 
635                         /* or else connect the pf to the sound and sample */
636 //                      else
637 //                      {
638                                 sound->newpackedfile = pf;
639                                 sound->sample->packedfile = pf;
640 //                      }
641                 }
642                 else 
643                 {
644                         if (G.f & G_DEBUG) printf("%s: File not found!\n", sound->name);
645                         sound->sample->type = SAMPLE_INVALID;
646                 }
647         }
648         /* if the sample ain't invalid, we're ready to go! */
649         else if (sound->sample->type != SAMPLE_INVALID)
650         {
651                 result = TRUE;
652         }
653
654         return result;
655 }
656
657
658
659 bSound* sound_new_sound(char* name)
660 {
661         bSound *sound = NULL;
662         int len, file;
663         char str[FILE_MAXDIR+FILE_MAXFILE];
664
665         if(ghSoundScene==NULL) sound_init_audio();
666
667         if (!G.scene->audio.mixrate) G.scene->audio.mixrate = 44100;
668         /* convert the name to absolute path */
669         strcpy(str, name);
670         BLI_convertstringcode(str, G.sce, G.scene->r.cfra);
671
672         /* check if the sample on disk can be opened */
673         file = open(str, O_BINARY|O_RDONLY);
674         
675         if (file != -1)
676         {
677                 close(file);
678
679
680                 /* do some name magic */
681                 len = strlen(name);
682                 while (len > 0 && name[len - 1] != '/' && name[len - 1] != '\\')
683                         len--;
684                 
685                 /* allocate some memory for the sound */
686                 sound = alloc_libblock(&G.main->sound, ID_SO, name + len);
687                 strcpy(sound->name, name);
688                 
689                 /* intialize and check the sample */
690                 sound_initialize_sample(sound);
691
692                 /* load the sample & check if this blender supports the sound format */
693 //              sound_load_sample(sound);
694
695                 if (sound->sample->type == SAMPLE_INVALID)
696                 {
697                         free_libblock(&G.main->sound, sound);
698                         sound = NULL;
699                 } 
700                 else
701                 {
702                         sound->volume = 1.0;
703                         sound->attenuation = 1.0;
704                         sound->distance = 1.0;
705                         sound->min_gain = 0.0;
706                         sound->max_gain = 1.0;
707                 }
708         }
709         
710         return (sound);
711 }
712
713
714
715 int sound_set_sample(bSound *sound, bSample *sample)
716 {
717         int result = TRUE;
718         
719         if(ghSoundScene==NULL) sound_init_audio();
720         
721         /* decrease the usernumber for this sample */
722         if (sound->sample)
723                 sound->sample->id.us--;
724
725         /* delete the soundobject */
726         if (sound->snd_sound)
727         {
728                 SND_RemoveSound(ghSoundScene, sound->snd_sound);
729                 sound->snd_sound = NULL;
730         }
731
732         /* connect the sample to the sound */
733         sound->sample = sample;
734         sound->newpackedfile = NULL;
735         
736         /* increase the usercount */
737         if (sound->sample)
738         {
739                 sound->sample->id.us++;
740
741                 /* and set the right pf */
742                 sound->newpackedfile = sample->packedfile;
743
744                 /* if the sampletype is unknown initialize it */
745                 if (sound->sample->type == SAMPLE_UNKNOWN)
746                 {
747                         sound_initialize_sample(sound);
748                         
749                         /* load the sample & check if this blender supports the sound format */
750                         if (!sound_load_sample(sound))
751                         {
752                                 result = FALSE;
753                         }
754                 }
755         }
756
757         return result;
758 }
759
760
761
762 bSample *sound_new_sample(bSound * sound)
763 {
764         bSample *sample = NULL;
765         int len;
766         char *name;
767         
768         if (sound != NULL)
769         {
770                 name = sound->name;     
771                 len = strlen(name);
772                 /* do some name magic */
773                 while (len > 0 && name[len - 1] != '/' && name[len - 1] != '\\')
774                         len--;
775                 
776                 /* allocate the memory for the sample */
777                 sample = alloc_libblock(samples, ID_SAMPLE, name + len);
778                 sample->data = &sample->fakedata[0];
779                 sample->type = SAMPLE_UNKNOWN;
780                 
781                 /* some default settings. We get divide by zero if these values are not set     */
782                 sample->channels = 1;
783                 sample->rate = 44100;
784                 sample->bits = 16;
785                 sample->alindex = SAMPLE_INVALID;
786
787                 /* convert sound->name to abolute filename */
788                 strcpy(sample->name, sound->name);
789                 BLI_convertstringcode(sample->name, G.sce, G.scene->r.cfra);
790                 
791                 /* connect the pf to the sample */
792                 if (sound->newpackedfile)
793                         sample->packedfile = sound->newpackedfile;
794                 else
795                         sample->packedfile = sound_find_packedfile(sound);
796         }
797         
798         return(sample);
799 }
800
801
802
803 /* find a sample that might already be loaded */
804 bSample* sound_find_sample(bSound* sound)
805 {
806         bSample* sample;
807         char name[FILE_MAXDIR + FILE_MAXFILE];
808         char samplename[FILE_MAXDIR + FILE_MAXFILE];
809         
810         // convert sound->name to abolute filename
811         strcpy(name, sound->name);
812         BLI_convertstringcode(name, G.sce, G.scene->r.cfra);
813         
814         /* search through the list of loaded samples */
815         sample = samples->first;
816         
817         while (sample)
818         {
819                 strcpy(samplename, sample->name);
820                 BLI_convertstringcode(samplename, G.sce, G.scene->r.cfra);
821                 
822                 if (strcmp(name, samplename) == 0)
823                 {
824                         break;
825                 }
826                 sample = sample->id.next;
827         }
828         
829         return (sample);
830 }
831
832
833
834 int sound_sample_is_null(bSound* sound)
835 {
836         int result = FALSE;
837         bSample* sample;
838         
839         if(ghSoundScene==NULL) sound_init_audio();
840         
841         /* find the right sample or else create one */
842         if (sound->sample == NULL)
843         {
844                 /* find... */
845                 sample = sound_find_sample(sound);
846
847                 /* or a new one? */
848                 if (sample == NULL)
849                         sample = sound_new_sample(sound);
850                 
851                 if (sound_set_sample(sound, sample))
852                         result = TRUE;
853         }
854
855         return result;
856 }
857
858
859
860 void sound_stop_all_sounds(void)
861 {
862 #if GAMEBLENDER == 1
863         if(ghSoundScene) {
864                 SND_StopAllSounds(ghSoundScene);
865                 SND_Proceed(ghAudioDeviceInterface, ghSoundScene);
866         }
867 #endif 
868 }
869
870
871
872 void sound_end_all_sounds(void)
873 {
874 #if GAMEBLENDER == 1
875         if(ghSoundScene) {
876                 sound_stop_all_sounds();
877                 SND_RemoveAllSounds(ghSoundScene);
878         }
879 #endif
880 }
881
882
883
884 void sound_play_sound(bSound* sound)
885 {
886 #if GAMEBLENDER == 1
887         if(ghSoundScene==NULL) sound_init_audio();
888         
889         /* first check if we want sound or not */
890         SND_IsPlaybackWanted(ghSoundScene);
891
892         /* stop all previous sounds */
893         SND_StopAllSounds(ghSoundScene);
894         
895         if (sound != NULL && sound->sample != NULL)
896         {
897                 /* load the sample if needed */
898                 if (sound_load_sample(sound))
899                 {
900                         /* set all kinds of parameters */
901                         SND_SetListenerGain(ghSoundScene, G.listener->gain);
902                         SND_SetDopplerFactor(ghSoundScene, G.listener->dopplerfactor);
903                         SND_SetDopplerVelocity(ghSoundScene, G.listener->dopplervelocity);
904                         
905                         SND_SetGain((SND_ObjectHandle)sound->snd_sound, (sound->volume));
906                         SND_SetPitch((SND_ObjectHandle)sound->snd_sound, (exp((sound->pitch / 12.0) * log(2.0))));
907                         
908                         if (sound->flags & SOUND_FLAGS_LOOP)
909                         {
910                                 SND_SetLoopMode((SND_ObjectHandle)sound->snd_sound, SND_LOOP_NORMAL);
911 #ifdef SOUND_UNDER_DEVELOPMENT
912 /*                              SND_SetLoopPoints((SND_ObjectHandle)sound->snd_sound, sound->loopstart, sound->loopend);
913 */
914 #endif
915                                 if (sound->flags & SOUND_FLAGS_BIDIRECTIONAL_LOOP)
916                                         SND_SetLoopMode((SND_ObjectHandle)sound->snd_sound, SND_LOOP_BIDIRECTIONAL);
917                                 else
918                                         SND_SetLoopMode((SND_ObjectHandle)sound->snd_sound, SND_LOOP_NORMAL);
919
920                         }
921                         else 
922                         {
923                                 SND_SetLoopMode((SND_ObjectHandle)sound->snd_sound, SND_LOOP_OFF);
924                         }
925                         
926                         if (sound->flags & SOUND_FLAGS_3D)
927                         {
928                                 SND_SetRollOffFactor((SND_ObjectHandle)sound->snd_sound, sound->attenuation);
929                                 SND_SetReferenceDistance((SND_ObjectHandle)sound->snd_sound, sound->distance);
930                                 SND_SetMinimumGain((SND_ObjectHandle)sound->snd_sound, sound->min_gain);
931                                 SND_SetMaximumGain((SND_ObjectHandle)sound->snd_sound, sound->max_gain);
932                         }
933                         else
934                         {
935                                 SND_SetRollOffFactor((SND_ObjectHandle)sound->snd_sound, 0);
936                                 SND_SetReferenceDistance((SND_ObjectHandle)sound->snd_sound, 1);
937                                 SND_SetMinimumGain((SND_ObjectHandle)sound->snd_sound, 1);
938                                 SND_SetMaximumGain((SND_ObjectHandle)sound->snd_sound, 1);
939                         }
940                         
941                         if (G.f & G_DEBUG) printf("Set pitch to: %f\n", SND_GetPitch((SND_ObjectHandle)sound->snd_sound));
942                         if (G.f & G_DEBUG) printf("Set gain to: %f\n", SND_GetGain((SND_ObjectHandle)sound->snd_sound));
943                         if (G.f & G_DEBUG) printf("Set looping to: %d\n", SND_GetLoopMode((SND_ObjectHandle)sound->snd_sound));
944                         
945                         /* play the sound */
946                         SND_StartSound(ghSoundScene, (SND_ObjectHandle)sound->snd_sound);
947
948                         /* update the device */
949                         SND_Proceed(ghAudioDeviceInterface, ghSoundScene);
950                 }
951         }
952         else 
953         {
954                 if (G.f & G_DEBUG)
955                 {
956                         printf("uninitialized sound !\n");              
957                         if (sound)
958                         {
959                                 printf("sound: %p\n", sound);
960                                 if (sound->sample)
961                                 {
962                                         printf("sample: %p\n", sound->sample);
963                                         if (sound->snd_sound)
964                                                 printf("hSoundObject: %p\n", sound->snd_sound);
965                                 }
966                         }
967                         else
968                         {
969                                 printf("sound == NULL\n");
970                         }
971                 }
972         }
973 #endif 
974 }
975
976
977
978 bSound *sound_find_sound(char *id_name)
979 {
980         bSound *sound;
981         
982         // look for sound with same *id* name
983         sound = G.main->sound.first;
984         while (sound)
985         {
986                 if (strcmp(sound->id.name + 2, id_name) == 0)
987                         break;
988
989                 sound = sound->id.next;
990         }
991         
992         return sound;
993 }
994
995 void sound_init_audio(void)
996 {
997         int noaudio;
998         SYS_SystemHandle hSystem = NULL;
999         
1000         if(ghSoundScene==NULL) {
1001                 
1002                 printf("sound init audio\n");
1003         
1004                 hSystem = SYS_GetSystem();
1005                 noaudio = SYS_GetCommandLineInt(hSystem,"noaudio",0);
1006                 
1007                 if (noaudio)/*(noaudio) intrr: disable game engine audio (openal) */
1008                         SND_SetDeviceType(snd_e_dummydevice);
1009         
1010                 ghAudioDeviceInterface = SND_GetAudioDevice();
1011                 ghSoundScene = SND_CreateScene(ghAudioDeviceInterface);
1012         }
1013 }
1014
1015
1016 int sound_get_mixrate(void)
1017 {
1018         return MIXRATE;
1019 }
1020
1021
1022 void sound_exit_audio(void)
1023 {
1024         if(ghSoundScene) {
1025                 SND_DeleteScene(ghSoundScene);
1026                 SND_ReleaseDevice();
1027         }
1028 }