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