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