Aegisub/aegisub/src/audio_renderer.h
Amar Takhar 774fb0f674 Fix all the headers in *., this includes:
* Wrapping all headers that are in agi_pre.h with AGI_PRE.
  * Sorting alphabetically.
  * Same operation as r3515.

Note: This is broken when precompiled headers are not in use, I'll fix that after this commit so the two changes don't get jumbled up.

Originally committed to SVN as r3525.
2009-09-11 02:36:34 +00:00

317 lines
11 KiB
C++

// Copyright (c) 2009, Niels Martin Hansen
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Aegisub Group nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Aegisub Project http://www.aegisub.org/
//
// $Id$
/// @file audio_renderer.h
/// @see audio_renderer.cpp
/// @ingroup audio_ui
///
/// Base classes for audio renderers (spectrum, waveform, ...)
#ifndef AGI_PRE
#include <memory>
#include <wx/dc.h>
#include <wx/gdicmn.h>
#endif
#include "block_cache.h"
// Some forward declarations for outside stuff
class AudioProvider;
// Forwards declarations for internal stuff
class AudioRendererBitmapProvider;
class AudioRenderer;
/// @class AudioRendererBitmapCacheBitmapFactory
/// @brief Produces wxBitmap objects for DataBlockCache storage for the audio renderer
struct AudioRendererBitmapCacheBitmapFactory {
/// The audio renderer we're producing bitmaps for
AudioRenderer *renderer;
/// @brief Constructor
/// @param renderer The audio renderer to produce bitmaps for
AudioRendererBitmapCacheBitmapFactory(AudioRenderer *renderer);
/// @brief Create a new bitmap
/// @param i Unused
/// @return A fresh wxBitmap
///
/// Produces a wxBitmap with dimensions pulled from our master AudioRenderer.
wxBitmap *ProduceBlock(int i);
/// @brief Delete a bitmap
/// @param bmp The bitmap to delete
///
/// Deletes said bitmap.
void DisposeBlock(wxBitmap *bmp);
/// @brief Calculate the size of bitmaps
/// @return The size of bitmaps created
size_t GetBlockSize() const;
};
/// The type of a bitmap cache
typedef DataBlockCache<wxBitmap, 8, AudioRendererBitmapCacheBitmapFactory> AudioRendererBitmapCache;
/// @class AudioRenderer
/// @brief Renders audio to bitmap images for display on screen
///
/// Manages a bitmap cache and paints to device contexts.
///
/// To implement a new audio renderer, see AudioRendererBitmapProvider.
class AudioRenderer {
friend struct AudioRendererBitmapCacheBitmapFactory;
/// Horizontal zoom level, samples per pixel
int pixel_samples;
/// Rendering height in pixels
int pixel_height;
/// Vertical zoom level/amplitude scale
float amplitude_scale;
/// Width of bitmaps to store in cache
const int cache_bitmap_width;
/// Cached bitmaps for normal audio ranges
AudioRendererBitmapCache bitmaps_normal;
/// Cached bitmaps for marked (selected) audio ranges
AudioRendererBitmapCache bitmaps_selected;
/// The maximum allowed size of the cache, in bytes
size_t cache_maxsize;
/// Actual renderer for bitmaps
AudioRendererBitmapProvider *renderer;
/// Audio provider to use as source
AudioProvider *provider;
/// @brief Make sure bitmap index i is in cache
/// @param i Index of bitmap to get into cache
/// @param selected Whether to get a "selected" state bitmap or not
/// @return The requested bitmap
///
/// Will attempt retrieving the requested bitmap from the cache, creating it
/// if the cache doesn't have it.
wxBitmap GetCachedBitmap(int i, bool selected);
/// @brief Update the block count in the bitmap caches
///
/// Should be called when the width of the virtual bitmap has changed, i.e.
/// when the samples-per-pixel resolution or the number of audio samples
/// has changed.
void ResetBlockCount();
public:
/// @brief Constructor
///
/// Initialises audio rendering to a do-nothing state. An audio provider and bitmap
/// provider must be set before the audio renderer is functional.
AudioRenderer();
/// @brief Destructor
///
/// Only destroys internal data, audio provider and bitmap providers are
/// owned by the consumer of audio rendering.
~AudioRenderer();
/// @brief Set horizontal zoom
/// @param pixel_samples Audio samples per pixel to render at
///
/// Changing the zoom level invalidates all cached bitmaps.
void SetSamplesPerPixel(int pixel_samples);
/// @brief Set rendering height
/// @param pixel_height Height in pixels to render at
///
/// Changing the rendering height invalidates all cached bitmaps.
void SetHeight(int pixel_height);
/// @brief Set vertical zoom
/// @param amplitude_scale Scaling factor
///
/// Changing the scaling factor invalidates all cached bitmaps.
///
/// A scaling factor of 1.0 is no scaling, a factor of 0.5 causes the audio to be
/// rendered as if it had half its actual amplitude, a factor of 2 causes the audio
/// to be rendered as if it had double amplitude. (The exact meaning of the scaling
/// depends on the bitmap provider used.)
void SetAmplitudeScale(float amplitude_scale);
/// @brief Set the maximum allowed cache size
/// @param max_size Size in bytes that may be used for caching
///
/// The given max size is not a hard limit and does generally not include overhead
/// added by the cache management. The allowed size might be distributed among
/// several separate objects.
///
/// Changing the max cache size does not trigger cache aging.
void SetCacheMaxSize(size_t max_size);
/// @brief Get horizontal zoom
/// @return Audio samples per pixel rendering at
int GetSamplesPerPixel() const { return pixel_samples; }
/// @brief Get rendering height
/// @return Height in pixels rendering at
int GetHeight() const { return pixel_height; }
/// @brief Get vertical zoom
/// @return The amplitude scaling factor
float GetAmplitudeScale() const { return amplitude_scale; }
/// @brief Change renderer
/// @param renderer New renderer to use
///
/// The consumer of audio rendering is responsible for creating, managing and destroying
/// audio bitmap providers (renderers). If a renderer was previously set with this function
/// and a new one is set, the consumer of audio rendering is still responsible for the
/// life of the old renderer.
///
/// A bitmap provider must be assigned to a newly created audio renderer before it
/// can be functional.
///
/// Changing renderer invalidates all cached bitmaps.
///
/// The old renderer will have its audio provider reset to 0 and the new renderer will
/// have its audio provider set to the current. This is done in part to ensure that
/// the renderers have any internal caches cleared.
void SetRenderer(AudioRendererBitmapProvider *renderer);
/// @brief Change audio provider
/// @param provider New audio provider to use
///
/// The consumer of audio rendering is responsible for managing audio providers.
/// If an audio provider was previously assigned to the audio renderer and a
/// new one is assigned, the consumer of audio rendering is still responsible for
/// the life of the old audio provider.
///
/// An audio provider must be assigned to a newly created audio renderer before it
/// can be functional.
///
/// Changing audio provider invalidates all cached bitmaps.
///
/// If a renderer is set, this will also set the audio provider for the renderer.
void SetAudioProvider(AudioProvider *provider);
/// @brief Render audio to a device context
/// @param dc The device context to draw to
/// @param origin Top left corner to render at, in the DC's coordinates
/// @param start First pixel from beginning of the audio stream to render
/// @param length Number of pixels of audio to render
/// @param selected Whether to render the audio as being selected or not
///
/// The first audio sample rendered is start*pixel_samples, and the number
/// of audio samples rendered is length*pixel_samples.
void Render(wxDC &dc, wxPoint origin, int start, int length, bool selected);
/// @brief Invalidate all cached data
///
/// Invalidates all cached bitmaps for another reason, usually as a signal that
/// implementation-defined data in the bitmap provider have been changed.
///
/// If the consumer of audio rendering changes properties of the bitmap renderer
/// that will affect the rendered images, it should call this function to ensure
/// the cache is kept consistent.
void Invalidate();
};
/// @class AudioRendererBitmapProvider
/// @brief Base class for audio renderer implementations
///
/// Derive from this class to implement a way to render audio to images.
class AudioRendererBitmapProvider {
protected:
/// Audio provider to use for rendering
AudioProvider *provider;
/// Horizontal zoom in samples per pixel
int pixel_samples;
/// Vertical zoom/amplitude scale factor
float amplitude_scale;
/// @brief Called when the audio provider changes
///
/// Implementations can override this method to do something when the audio provider is changed
virtual void OnSetProvider() { }
/// @brief Called when horizontal zoom changes
///
/// Implementations can override this method to do something when the horizontal zoom is changed
virtual void OnSetSamplesPerPixel() { }
/// @brief Called when vertical zoom changes
///
/// Implementations can override this method to do something when the vertical zoom is changed
virtual void OnSetAmplitudeScale() { }
public:
/// @brief Constructor
AudioRendererBitmapProvider() : provider(0), pixel_samples(0) { };
/// @brief Destructor
~AudioRendererBitmapProvider() { }
/// @brief Rendering function
/// @param bmp Bitmap to render to
/// @param start First pixel from beginning of the audio stream to render
/// @param selected Whether to render the audio as being selected or not
///
/// Deriving classes must implement this method. The bitmap in bmp holds
/// the width and height to render.
virtual void Render(wxBitmap &bmp, int start, bool selected) = 0;
/// @brief Change audio provider
/// @param provider Audio provider to change to
void SetProvider(AudioProvider *provider);
/// @brief Change horizontal zoom
/// @param pixel_samples Samples per pixel to zoom to
void SetSamplesPerPixel(int pixel_samples);
/// @brief Change vertical zoom
/// @param amplitude_scale Scaling factor to zoom to
void SetAmplitudeScale(float amplitude_scale);
/// @brief Age any caches the renderer might keep
/// @param max_size Maximum size in bytes the caches should be
///
/// Deriving classes should override this method if they implement any
/// kind of caching.
virtual void AgeCache(size_t max_size) { }
};