📄 sound.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / 3D rendering module * * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * GPAC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */#include "render3d_nodes.h"typedef struct{ GF_SoundInterface snd_ifce; SFVec3f pos;} Sound2DStack;/*sound2D wraper - spacialization is not supported yet*/static void RenderSound2D(GF_Node *node, void *rs, Bool is_destroy){ RenderEffect3D *eff = (RenderEffect3D*) rs; M_Sound2D *snd = (M_Sound2D *)node; Sound2DStack *st = (Sound2DStack *)gf_node_get_private(node); if (is_destroy) { free(st); return; } if (!snd->source) return; /*this implies no DEF/USE for real location...*/ st->pos.x = snd->location.x; st->pos.y = snd->location.y; st->pos.z = 0; gf_mx_apply_vec(&eff->model_matrix, &st->pos); eff->sound_holder = &st->snd_ifce; gf_node_render((GF_Node *) snd->source, eff); eff->sound_holder = NULL; /*never cull Sound2d*/ eff->trav_flags |= TF_DONT_CULL;}static Bool SND2D_GetChannelVolume(GF_Node *node, Fixed *vol){ Fixed volume = ((M_Sound2D *)node)->intensity; vol[0] = vol[1] = vol[2] = vol[3] = vol[4] = vol[5] = volume; return (volume==FIX_ONE) ? 0 : 1;}static u8 SND2D_GetPriority(GF_Node *node){ return 255;}void R3D_InitSound2D(Render3D *sr, GF_Node *node){ Sound2DStack *snd; GF_SAFEALLOC(snd, Sound2DStack); snd->snd_ifce.GetPriority = SND2D_GetPriority; snd->snd_ifce.GetChannelVolume = SND2D_GetChannelVolume; snd->snd_ifce.owner = node; gf_node_set_private(node, snd); gf_node_set_callback_function(node, RenderSound2D);}static Fixed snd_compute_gain(Fixed min_b, Fixed min_f, Fixed max_b, Fixed max_f, SFVec3f pos){ Fixed sqpos_x, sqpos_z; Fixed y_pos, x_pos, dist_ellip, viewp_dist, dist_from_foci_min, dist_from_foci_max, d_min, d_max, sqb_min, sqb_max; Fixed a_in = (min_f+min_b)/2; Fixed b_in = gf_sqrt(gf_mulfix(min_b, min_f)); Fixed alpha_min = (min_f-min_b)/2; Fixed dist_foci_min = (min_f-min_b); Fixed a_out = (max_f+max_b)/2; //first ellipse axis Fixed b_out = gf_sqrt(gf_mulfix(max_b, max_f)); Fixed alpha_max = (max_f-max_b)/2; //origo from focus Fixed dist_foci_max = (max_f-max_b); Fixed x_min = 0; Fixed x_max = 0; Fixed y_min = 0; Fixed y_max = 0; Fixed k = (ABS(pos.z) >= FIX_EPSILON) ? gf_divfix(pos.x, pos.z) : 0; sqpos_x = gf_mulfix(pos.x, pos.x); sqpos_z = gf_mulfix(pos.z, pos.z); dist_from_foci_min = gf_sqrt(sqpos_z + sqpos_x) + gf_sqrt( gf_mulfix(pos.z - dist_foci_min, pos.z - dist_foci_min) + sqpos_x); dist_from_foci_max = gf_sqrt(sqpos_z + sqpos_x) + gf_sqrt( gf_mulfix(pos.z - dist_foci_max, pos.z - dist_foci_max) + sqpos_x); d_min = min_f+min_b; d_max = max_f+max_b; if(dist_from_foci_max > d_max) return 0; else if (dist_from_foci_min <= d_min) return FIX_ONE; sqb_min = gf_mulfix(b_in, b_in); sqb_max = gf_mulfix(b_out, b_out); if (ABS(pos.z) > FIX_ONE/10000) { s32 sign = (pos.z>0) ? 1 : -1; Fixed a_in_k_sq, a_out_k_sq; a_in_k_sq = gf_mulfix(a_in, k); a_in_k_sq = gf_mulfix(a_in_k_sq, a_in_k_sq); x_min = gf_mulfix(alpha_min, sqb_min) + sign*gf_mulfix( gf_mulfix(a_in, b_in), gf_sqrt(a_in_k_sq + sqb_min - gf_mulfix( gf_mulfix(alpha_min, k), gf_mulfix(alpha_min, k)))); x_min = gf_divfix(x_min, sqb_min + a_in_k_sq); y_min = gf_mulfix(k, x_min); a_out_k_sq = gf_mulfix(a_out, k); a_out_k_sq = gf_mulfix(a_out_k_sq, a_out_k_sq); x_max = gf_mulfix(alpha_max, sqb_max) + sign*gf_mulfix( gf_mulfix(a_out, b_out), gf_sqrt( a_out_k_sq + sqb_max - gf_mulfix( gf_mulfix(alpha_max, k), gf_mulfix(alpha_max, k)))); x_max = gf_divfix(x_max, sqb_max + a_out_k_sq); y_max = gf_mulfix(k, x_max); } else { x_min = x_max = 0; y_min = gf_mulfix(b_in, gf_sqrt(FIX_ONE - gf_mulfix( gf_divfix(alpha_min,a_in), gf_divfix(alpha_min,a_in)) ) ); y_max = gf_mulfix(b_out, gf_sqrt(FIX_ONE - gf_mulfix( gf_divfix(alpha_max,a_out), gf_divfix(alpha_max,a_out)) ) ); } y_pos = gf_sqrt(sqpos_x) - y_min; x_pos = pos.z - x_min; x_max -= x_min; y_max -= y_min; dist_ellip = gf_sqrt( gf_mulfix(y_max, y_max) + gf_mulfix(x_max, x_max)); viewp_dist = gf_sqrt( gf_mulfix(y_pos, y_pos) + gf_mulfix(x_pos, x_pos)); viewp_dist = gf_divfix(viewp_dist, dist_ellip); return FLT2FIX ( (Float) pow(10.0,- FIX2FLT(viewp_dist)));}typedef struct{ GF_SoundInterface snd_ifce; GF_Matrix mx; SFVec3f last_pos; Bool identity; /*local system*/ Fixed intensity; Fixed lgain, rgain;} SoundStack;static void RenderSound(GF_Node *node, void *rs, Bool is_destroy){ RenderEffect3D *eff = (RenderEffect3D*) rs; M_Sound *snd = (M_Sound *)node; SoundStack *st = (SoundStack *)gf_node_get_private(node); if (is_destroy) { free(st); return; } if (!snd->source) return; eff->sound_holder = &st->snd_ifce; /*forward in case we're switched off*/ if (eff->trav_flags & GF_SR_TRAV_SWITCHED_OFF) { gf_node_render((GF_Node *) snd->source, eff); } else if (eff->traversing_mode==TRAVERSE_GET_BOUNDS) { /*we can't cull sound since*/ eff->trav_flags |= TF_DONT_CULL; } else if (eff->traversing_mode==TRAVERSE_SORT) { GF_Matrix mx; SFVec3f usr, snd_dir, pos; Fixed mag, ang; /*this implies no DEF/USE for real location...*/ gf_mx_copy(st->mx, eff->model_matrix); gf_mx_copy(mx, eff->model_matrix); gf_mx_inverse(&mx); snd_dir = snd->direction; gf_vec_norm(&snd_dir); /*get user location*/ usr = eff->camera->position; gf_mx_apply_vec(&mx, &usr); /*recenter to ellipse focal*/ gf_vec_diff(usr, usr, snd->location); mag = gf_vec_len(usr); if (!mag) mag = FIX_ONE/10; ang = gf_divfix(gf_vec_dot(snd_dir, usr), mag); usr.z = gf_mulfix(ang, mag); usr.x = gf_sqrt(gf_mulfix(mag, mag) - gf_mulfix(usr.z, usr.z)); usr.y = 0; if (!gf_vec_equal(usr, st->last_pos)) { st->intensity = snd_compute_gain(snd->minBack, snd->minFront, snd->maxBack, snd->maxFront, usr); st->intensity = gf_mulfix(st->intensity, snd->intensity); st->last_pos = usr; } st->identity = (st->intensity==FIX_ONE) ? 1 : 0; if (snd->spatialize) { Fixed ang, sign; SFVec3f cross; pos = snd->location; gf_mx_apply_vec(&eff->model_matrix, &pos); gf_vec_diff(pos, pos, eff->camera->position); gf_vec_diff(usr, eff->camera->target, eff->camera->position); gf_vec_norm(&pos); gf_vec_norm(&usr); ang = gf_acos(gf_vec_dot(usr, pos)); /*get orientation*/ cross = gf_vec_cross(usr, pos); sign = gf_vec_dot(cross, eff->camera->up); if (sign>0) ang *= -1; ang = (FIX_ONE + gf_sin(ang)) / 2; st->lgain = (FIX_ONE - gf_mulfix(ang, ang)); st->rgain = FIX_ONE - gf_mulfix(FIX_ONE - ang, FIX_ONE - ang); /*renorm between 0 and 1*/ st->lgain = gf_mulfix(st->lgain, 4*st->intensity/3); st->rgain = gf_mulfix(st->rgain, 4*st->intensity/3); if (st->identity && ((st->lgain!=FIX_ONE) || (st->rgain!=FIX_ONE))) st->identity = 0; } else { st->lgain = st->rgain = FIX_ONE; } gf_node_render((GF_Node *) snd->source, eff); } eff->sound_holder = NULL;}static Bool SND_GetChannelVolume(GF_Node *node, Fixed *vol){ M_Sound *snd = (M_Sound *)node; SoundStack *st = (SoundStack *)gf_node_get_private(node); vol[2] = vol[3] = vol[4] = vol[5] = st->intensity; if (snd->spatialize) { vol[0] = st->lgain; vol[1] = st->rgain; } else { vol[0] = vol[1] = st->intensity; } return !st->identity;}static u8 SND_GetPriority(GF_Node *node){ return (u8) ((M_Sound *)node)->priority*255;}void R3D_InitSound(Render3D *sr, GF_Node *node){ SoundStack *snd; GF_SAFEALLOC(snd, SoundStack); snd->snd_ifce.GetChannelVolume = SND_GetChannelVolume; snd->snd_ifce.GetPriority = SND_GetPriority; snd->snd_ifce.owner = node; gf_node_set_private(node, snd); gf_node_set_callback_function(node, RenderSound);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -