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