/*
  Copyright (C) 2010-2011  Charles Pence <charles@charlespence.net>
  Copyright (C) 1996-1997  Id Software, Inc.

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program 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 General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "../pch.h"
#include "../quakedef.h"
#include "channel.h"
#include "sample.h"

namespace sound
{

Channel::Channel() : mix_channel_(-1), looping_(false),
    left_vol_(0), right_vol_(0), master_vol_(0), entity_num_(-1),
    entity_channel_(0), dist_mult_(1.0f)
{
    VectorCopy(vec3_origin, origin_);
}

void Channel::Allocate()
{
    if (mix_channel_ != -1)
        return;
    
    int num_channels = Mix_AllocateChannels(-1);
    Mix_AllocateChannels(num_channels + 1);
    mix_channel_ = num_channels;
}

void Channel::Spatialize(vec3_t listener_origin, vec3_t listener_right)
{
    // anything coming from the view entity will always be full volume
    if (entity_num_ == cl.viewentity)
    {
        left_vol_ = (byte)(master_vol_ * 255.0f);
        right_vol_ = (byte)(master_vol_ * 255.0f);
        return;
    }

    // calculate stereo separation and distance attenuation
    vec3_t source_vec;
    float dot, dist;
    
    VectorSubtract(origin_, listener_origin, source_vec);
    dist = VectorNormalize(source_vec) * dist_mult_;
    dot = DotProduct(listener_right, source_vec);

    float rscale = 1.0 + dot;
    float lscale = 1.0 - dot;

    // add in distance effect
    float scale = (1.0 - dist) * rscale;
    
    int v = (int)(master_vol_ * 255.0f) * scale;
    if (v < 0) v = 0;
    right_vol_ = v;

    scale = (1.0 - dist) * lscale;
    v = (int)(master_vol_ * 255.0f) * scale;
    if (v < 0) v = 0;
    left_vol_ = v;
}

}