// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "tone_generators.h"

#include <assert.h>

#include <algorithm>
#include <limits>

namespace autotest_client {
namespace audio {

namespace {

template <typename T>
void* WriteSample(void* data, double magnitude) {
  // Handle unsigned.
  if (std::numeric_limits<T>::min() == 0) {
    magnitude += 1.0;
    magnitude /= 2.0;
  }

  T* sample_data = reinterpret_cast<T*>(data);
  *sample_data = magnitude * std::numeric_limits<T>::max();
  return sample_data + 1;
}

void* WriteSampleForFormat(void* data, double magnitude, SampleFormat format) {
  if (format.type() == SampleFormat::kPcmU8) {
    return WriteSample<unsigned char>(data, magnitude);

  } else if (format.type() == SampleFormat::kPcmS16) {
    return WriteSample<int16_t>(data, magnitude);

  } else if (format.type() == SampleFormat::kPcmS24) {
    unsigned char* sample_data = reinterpret_cast<unsigned char*>(data);
    int32_t value = magnitude * (1 << 23);  // 1 << 23 24-bit singed max().
    sample_data[0] = value & 0xff;
    sample_data[1] = (value >> 8) & 0xff;
    sample_data[2] = (value >> 16) & 0xff;
    return sample_data + 3;

  } else if (format.type() == SampleFormat::kPcmS32) {
    return WriteSample<int32_t>(data, magnitude);
  }

  // Return NULL, which should crash the caller.
  assert(false);
  return NULL;
}

}  // namespace

SingleToneGenerator::SingleToneGenerator(int sample_rate, double length_sec)
    : frames_generated_(0),
      frames_wanted_(length_sec * sample_rate),
      fade_frames_(0),  // Calculated below.
      frequency_(0.0f),
      sample_rate_(sample_rate),
      cur_vol_(1.0),
      start_vol_(1.0),
      inc_vol_(0.0) {

  // Use a 5ms fade.
  const double kFadeTimeSec = 0.01;

  // Only fade if the fade won't take more than 1/2 the tone.
  if (length_sec > (kFadeTimeSec * 4)) {
    fade_frames_ = kFadeTimeSec * sample_rate;
  }
}

SingleToneGenerator::~SingleToneGenerator() {
}

void SingleToneGenerator::SetVolumes(double start_vol, double end_vol) {
  cur_vol_ = start_vol_ = start_vol;
  inc_vol_ = (end_vol - start_vol) / frames_wanted_;
}

void SingleToneGenerator::Reset(double frequency) {
  frequency_ = frequency;
  frames_generated_ = 0;
  cur_vol_ = start_vol_;
}

void SingleToneGenerator::GetFrames(SampleFormat format,
                                    int channels,
                                    const std::set<int>& active_channels,
                                    void* data,
                                    size_t* buf_size) {
  const size_t kBytesPerFrame = channels * format.bytes();
  void* cur = data;
  size_t frames = *buf_size / kBytesPerFrame;
  size_t frames_written;
  for (frames_written = 0; frames_written < frames; ++frames_written) {
    if (!HasMoreFrames()) {
      break;
    }

    double frame_magnitude = 
        GetFadeMagnitude() *
        tone_wave_.Next(sample_rate_, frequency_) * cur_vol_;
    cur_vol_ += inc_vol_;
    for (int c = 0; c < channels; ++c) {
      if (active_channels.find(c) != active_channels.end()) {
        cur = WriteSampleForFormat(cur, frame_magnitude, format);
      } else {
        // Silence the non-active channels.
        cur = WriteSampleForFormat(cur, 0.0f, format);
      }
    }

    ++frames_generated_;
  }

  *buf_size = frames_written * kBytesPerFrame;
}

bool SingleToneGenerator::HasMoreFrames() const {
  return frames_generated_ < frames_wanted_;
}

double SingleToneGenerator::GetFadeMagnitude() const {
  // Fade in.
  int frames_left = frames_wanted_ - frames_generated_;
  if (frames_generated_ < fade_frames_) {
    return sin(kHalfPi * frames_generated_ / fade_frames_);
  } else if (frames_left < fade_frames_) {
    return sin(kHalfPi * frames_left / fade_frames_);
  } else {
    return 1.0f;
  }
}

// A# minor harmoic scale is: A#, B# (C), C#, D#, E# (F), F#, G## (A). 
const double ASharpMinorGenerator::kNoteFrequencies[] = {
  466.16, 523.25, 554.37, 622.25, 698.46, 739.99, 880.00, 932.33,
  932.33, 880.00, 739.99, 698.46, 622.25, 554.37, 523.25, 466.16, 
};

ASharpMinorGenerator::ASharpMinorGenerator(int sample_rate,
                                           double tone_length_sec)
    : tone_generator_(sample_rate, tone_length_sec),
      cur_note_(0) {
  tone_generator_.Reset(kNoteFrequencies[cur_note_]);
}

ASharpMinorGenerator::~ASharpMinorGenerator() {
}

void ASharpMinorGenerator::SetVolumes(double start_vol, double end_vol) {
  tone_generator_.SetVolumes(start_vol, end_vol);
}

void ASharpMinorGenerator::Reset() {
  cur_note_ = 0;
  tone_generator_.Reset(kNoteFrequencies[cur_note_]);
}

void ASharpMinorGenerator::GetFrames(SampleFormat format,
                                     int channels,
                                     const std::set<int>& active_channels,
                                     void* data,
                                     size_t* buf_size) {
  if (!HasMoreFrames()) {
    *buf_size = 0;
    return;
  }

  // Go to next note if necessary.
  if (!tone_generator_.HasMoreFrames()) {
    tone_generator_.Reset(kNoteFrequencies[++cur_note_]);
  }
  
  tone_generator_.GetFrames(format, channels, active_channels, data, buf_size);
}

bool ASharpMinorGenerator::HasMoreFrames() const {
  return cur_note_ < kNumNotes - 1 || tone_generator_.HasMoreFrames();
}

}  // namespace audio
}  // namespace autotest_client
