forked from mia/Aegisub
Add Doxygen documentation to audio spectrum code
Originally committed to SVN as r3343.
This commit is contained in:
parent
d8200c669e
commit
e42d184ec4
2 changed files with 184 additions and 204 deletions
|
@ -53,70 +53,82 @@
|
||||||
#include <wx/log.h>
|
#include <wx/log.h>
|
||||||
|
|
||||||
|
|
||||||
// Audio spectrum FFT data cache
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
/// @class AudioSpectrumCache
|
/// @class AudioSpectrumCache
|
||||||
/// @brief DOCME
|
/// @brief Base class for the frequency-power cache tree.
|
||||||
///
|
///
|
||||||
/// DOCME
|
/// The cached frequency-power are kept in a shallow tree-structure composed of
|
||||||
|
/// intermediate branches and final leaves, both accessed through a common
|
||||||
|
/// interface, which is this class.
|
||||||
|
///
|
||||||
|
/// The term "cache line" here means the frequency-power data derived from
|
||||||
|
/// some range of audio samples, calculated by a single FFT.
|
||||||
class AudioSpectrumCache {
|
class AudioSpectrumCache {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// DOCME
|
/// The type of frequency-power data at one point in time.
|
||||||
typedef std::vector<float> CacheLine;
|
typedef std::vector<float> CacheLine;
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
/// The type of timestamps for last access.
|
||||||
typedef unsigned int CacheAccessTime;
|
typedef unsigned int CacheAccessTime;
|
||||||
|
|
||||||
/// DOCME
|
/// Holds last-access data for a range of range of cache lines.
|
||||||
|
/// Ranges can overlap, in case overlapping FFT's are used to increase precision.
|
||||||
struct CacheAgeData {
|
struct CacheAgeData {
|
||||||
|
/// Last time this range of cache lines were accessed.
|
||||||
/// DOCME
|
|
||||||
CacheAccessTime access_time;
|
CacheAccessTime access_time;
|
||||||
|
/// First line in the range.
|
||||||
/// DOCME
|
|
||||||
unsigned long first_line;
|
unsigned long first_line;
|
||||||
|
/// Number of lines in the range.
|
||||||
|
unsigned long num_lines;
|
||||||
|
|
||||||
/// DOCME
|
/// @brief Comparison operator for sorting age data by last access time.
|
||||||
unsigned long num_lines; // includes overlap-lines
|
/// @param second The age data structure to compare against.
|
||||||
|
/// @return Returns true if last access time of this range is less than that of the other.
|
||||||
/// @brief DOCME
|
|
||||||
/// @param second
|
|
||||||
/// @return
|
|
||||||
///
|
|
||||||
bool operator< (const CacheAgeData& second) const { return access_time < second.access_time; }
|
bool operator< (const CacheAgeData& second) const { return access_time < second.access_time; }
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief Constructor.
|
||||||
/// @param t
|
/// @param t Initial access time to set.
|
||||||
/// @param first
|
/// @param first First line in the range.
|
||||||
/// @param num
|
/// @param num Number of lines in the range.
|
||||||
///
|
///
|
||||||
CacheAgeData(CacheAccessTime t, unsigned long first, unsigned long num) : access_time(t), first_line(first), num_lines(num) { }
|
CacheAgeData(CacheAccessTime t, unsigned long first, unsigned long num) : access_time(t), first_line(first), num_lines(num) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
/// DOCME
|
/// Type of a list of cache age data.
|
||||||
typedef std::vector<CacheAgeData> CacheAgeList;
|
typedef std::vector<CacheAgeData> CacheAgeList;
|
||||||
|
|
||||||
// Get the overlap'th overlapping FFT in FFT group i, generating it if needed
|
/// @brief Retrieve frequency-power data.
|
||||||
|
/// @param i Index of the block to get the line from.
|
||||||
|
/// @param overlap Index of the overlap in the block to get the line for.
|
||||||
|
/// @param created [out] Set to true if the data had to be calculated, false if the data
|
||||||
|
/// was found in cache.
|
||||||
|
/// @param access_time Timestamp to mark the cache data as accessed at.
|
||||||
|
/// @return Returns a reference to the frequency-power data requested.
|
||||||
|
///
|
||||||
|
/// The data are fetched from the cache if they are cached, otherwise the required
|
||||||
|
/// audio data are retrieved, the FFT derived, and power data calculated.
|
||||||
virtual CacheLine& GetLine(unsigned long i, unsigned int overlap, bool &created, CacheAccessTime access_time) = 0;
|
virtual CacheLine& GetLine(unsigned long i, unsigned int overlap, bool &created, CacheAccessTime access_time) = 0;
|
||||||
|
|
||||||
// Get the total number of cache lines currently stored in this cache node's sub tree
|
/// @brief Get the size of the cache subtree.
|
||||||
|
/// @return Number of lines stored in all nodes below this one in the tree.
|
||||||
virtual size_t GetManagedLineCount() = 0;
|
virtual size_t GetManagedLineCount() = 0;
|
||||||
|
|
||||||
// Append to a list of last access times to the cache
|
/// @brief Retrieve cache access times.
|
||||||
|
/// @param ages [in,out] List to append age data of managed lines to.
|
||||||
|
///
|
||||||
|
/// Existing contents of the list is kept, new entries are added to the end.
|
||||||
virtual void GetLineAccessTimes(CacheAgeList &ages) = 0;
|
virtual void GetLineAccessTimes(CacheAgeList &ages) = 0;
|
||||||
|
|
||||||
// Delete the cache storage starting with the given line id
|
/// @brief Remove data from the cache.
|
||||||
// Return true if the object called on is empty and can safely be deleted too
|
/// @param line_id Index of the block the cache node to remove starts at.
|
||||||
|
/// @return Returns true if the object the method was called on no longer manages
|
||||||
|
// any cache lines and can safely be deleted.
|
||||||
virtual bool KillLine(unsigned long line_id) = 0;
|
virtual bool KillLine(unsigned long line_id) = 0;
|
||||||
|
|
||||||
|
|
||||||
/// @brief // Set the FFT size used
|
/// @brief Set the FFT size used globally.
|
||||||
/// @param new_length
|
/// @param new_length Number of audio samples to use in calculation.
|
||||||
///
|
|
||||||
static void SetLineLength(unsigned long new_length)
|
static void SetLineLength(unsigned long new_length)
|
||||||
{
|
{
|
||||||
line_length = new_length;
|
line_length = new_length;
|
||||||
|
@ -124,62 +136,50 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief Destructor, does nothing in base class.
|
||||||
///
|
|
||||||
virtual ~AudioSpectrumCache() {};
|
virtual ~AudioSpectrumCache() {};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/// DOCME
|
/// Global template for cache lines.
|
||||||
static CacheLine null_line;
|
static CacheLine null_line;
|
||||||
|
/// Number of audio samples used for power calculation, determining the
|
||||||
/// DOCME
|
/// frequency resolution of the frequency-power data.
|
||||||
static unsigned long line_length;
|
static unsigned long line_length;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Actual variables allocating memory for the static class members
|
||||||
/// DOCME
|
|
||||||
AudioSpectrumCache::CacheLine AudioSpectrumCache::null_line;
|
AudioSpectrumCache::CacheLine AudioSpectrumCache::null_line;
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
unsigned long AudioSpectrumCache::line_length;
|
unsigned long AudioSpectrumCache::line_length;
|
||||||
|
|
||||||
|
|
||||||
// Bottom level FFT cache, holds actual power data itself
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
/// @class FinalSpectrumCache
|
/// @class FinalSpectrumCache
|
||||||
/// @brief DOCME
|
/// @brief Leaf node in frequency-power cache tree, holds actual data.
|
||||||
///
|
///
|
||||||
/// DOCME
|
/// This class stores frequency-power data and is responsible for calculating it as well.
|
||||||
class FinalSpectrumCache : public AudioSpectrumCache {
|
class FinalSpectrumCache : public AudioSpectrumCache {
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/// DOCME
|
/// The stored data.
|
||||||
std::vector<CacheLine> data;
|
std::vector<CacheLine> data;
|
||||||
|
|
||||||
/// DOCME
|
unsigned long start, ///< Start of block range
|
||||||
|
length; ///< Number of blocks
|
||||||
|
unsigned int overlaps; ///< How many lines per block
|
||||||
|
|
||||||
/// DOCME
|
/// Last access time for cache management.
|
||||||
unsigned long start, length; // start and end of range
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
unsigned int overlaps;
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
CacheAccessTime last_access;
|
CacheAccessTime last_access;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief Returns stored frequency-power data.
|
||||||
/// @param i
|
/// @param i Index of the block to get the line from.
|
||||||
/// @param overlap
|
/// @param overlap Index of the overlap in the block to get the line for.
|
||||||
/// @param created
|
/// @param created [out] Set to true if the data had to be calculated, false if the data
|
||||||
/// @param access_time
|
/// was found in cache.
|
||||||
/// @return
|
/// @param access_time Timestamp to mark the cache data as accessed at.
|
||||||
///
|
/// @return Returns a reference to the frequency-power data requested.
|
||||||
CacheLine& GetLine(unsigned long i, unsigned int overlap, bool &created, CacheAccessTime access_time)
|
CacheLine& GetLine(unsigned long i, unsigned int overlap, bool &created, CacheAccessTime access_time)
|
||||||
{
|
{
|
||||||
last_access = access_time;
|
last_access = access_time;
|
||||||
|
@ -192,40 +192,42 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief Get number of lines in cache.
|
||||||
/// @return
|
/// @return Number of lines stored at this leaf.
|
||||||
///
|
|
||||||
size_t GetManagedLineCount()
|
size_t GetManagedLineCount()
|
||||||
{
|
{
|
||||||
return data.size();
|
return data.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief Add own cache age data to list of age data.
|
||||||
/// @param ages
|
/// @param ages [in,out] List to add cache age data to.
|
||||||
///
|
///
|
||||||
|
/// Produces a single cache age data object, representing the entire node,
|
||||||
|
/// and adds it to the list.
|
||||||
void GetLineAccessTimes(CacheAgeList &ages)
|
void GetLineAccessTimes(CacheAgeList &ages)
|
||||||
{
|
{
|
||||||
ages.push_back(CacheAgeData(last_access, start, data.size()));
|
ages.push_back(CacheAgeData(last_access, start, data.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief Return true if this is the line to remove.
|
||||||
/// @param line_id
|
/// @param line_id Index of the block the cache node to remove starts at.
|
||||||
/// @return
|
/// @return Returns true if this is the cache block to remove.
|
||||||
///
|
///
|
||||||
|
/// This function won't actually delete anything, instead it is the responsibility
|
||||||
|
/// of the caller to delete the cache node if this function returns true.
|
||||||
bool KillLine(unsigned long line_id)
|
bool KillLine(unsigned long line_id)
|
||||||
{
|
{
|
||||||
return start == line_id;
|
return start == line_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief Constructor, derives FFT and calculates frequency-power data.
|
||||||
/// @param provider
|
/// @param provider Audio provider to get audio from.
|
||||||
/// @param _start
|
/// @param _start Index of first block to calculate data for.
|
||||||
/// @param _length
|
/// @param _length Number of blocks to calculate data for.
|
||||||
/// @param _overlaps
|
/// @param _overlaps Number of lines to calculate per block.
|
||||||
///
|
|
||||||
FinalSpectrumCache(AudioProvider *provider, unsigned long _start, unsigned long _length, unsigned int _overlaps)
|
FinalSpectrumCache(AudioProvider *provider, unsigned long _start, unsigned long _length, unsigned int _overlaps)
|
||||||
{
|
{
|
||||||
start = _start;
|
start = _start;
|
||||||
|
@ -295,8 +297,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief Destructor, does nothing.
|
||||||
///
|
///
|
||||||
|
/// All data is managed by C++ types and gets deleted when those types'
|
||||||
|
/// destructors are implicitly run.
|
||||||
virtual ~FinalSpectrumCache()
|
virtual ~FinalSpectrumCache()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -304,48 +308,37 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Non-bottom-level cache, refers to other caches to do the work
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
/// @class IntermediateSpectrumCache
|
/// @class IntermediateSpectrumCache
|
||||||
/// @brief DOCME
|
/// @brief Intermediate node in the spectrum cache tree.
|
||||||
///
|
///
|
||||||
/// DOCME
|
/// References further nodes in the spectrum cache tree and delegates operations to them.
|
||||||
class IntermediateSpectrumCache : public AudioSpectrumCache {
|
class IntermediateSpectrumCache : public AudioSpectrumCache {
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/// DOCME
|
/// The child-nodes in the cache tree.
|
||||||
std::vector<AudioSpectrumCache*> sub_caches;
|
std::vector<AudioSpectrumCache*> sub_caches;
|
||||||
|
|
||||||
/// DOCME
|
unsigned long start, ///< DOCME
|
||||||
|
length, ///< DOCME
|
||||||
|
subcache_length; ///< DOCME
|
||||||
|
unsigned int overlaps; ///< Number of overlaps used.
|
||||||
|
bool subcaches_are_final; ///< Are the children leaf nodes?
|
||||||
|
int depth; ///< How deep is this in the tree.
|
||||||
|
|
||||||
/// DOCME
|
/// Audio provider to pass on to child nodes.
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
unsigned long start, length, subcache_length;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
unsigned int overlaps;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
bool subcaches_are_final;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
int depth;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
AudioProvider *provider;
|
AudioProvider *provider;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief Delegate line retrieval to a child node.
|
||||||
/// @param i
|
/// @param i Index of the block to get the line from.
|
||||||
/// @param overlap
|
/// @param overlap Index of the overlap in the block to get the line for.
|
||||||
/// @param created
|
/// @param created [out] Set to true if the data had to be calculated, false if the data
|
||||||
/// @param access_time
|
/// was found in cache.
|
||||||
/// @return
|
/// @param access_time Timestamp to mark the cache data as accessed at.
|
||||||
|
/// @return Returns a reference to the frequency-power data requested.
|
||||||
///
|
///
|
||||||
|
/// Will create the required child node if it doesn't exist yet.
|
||||||
CacheLine &GetLine(unsigned long i, unsigned int overlap, bool &created, CacheAccessTime access_time)
|
CacheLine &GetLine(unsigned long i, unsigned int overlap, bool &created, CacheAccessTime access_time)
|
||||||
{
|
{
|
||||||
if (i >= start && i-start <= length) {
|
if (i >= start && i-start <= length) {
|
||||||
|
@ -369,9 +362,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief Iterate all direct children and return the sum of their managed line count.
|
||||||
/// @return
|
/// @return Returns the sum of the managed line count of all children.
|
||||||
///
|
|
||||||
size_t GetManagedLineCount()
|
size_t GetManagedLineCount()
|
||||||
{
|
{
|
||||||
size_t res = 0;
|
size_t res = 0;
|
||||||
|
@ -383,9 +375,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief Get access time data for all child nodes in cache tree.
|
||||||
/// @param ages
|
/// @param ages [in,out] List for child nodes to add their data to.
|
||||||
///
|
|
||||||
void GetLineAccessTimes(CacheAgeList &ages)
|
void GetLineAccessTimes(CacheAgeList &ages)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < sub_caches.size(); ++i) {
|
for (size_t i = 0; i < sub_caches.size(); ++i) {
|
||||||
|
@ -395,10 +386,14 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief Remove block with given index from cache.
|
||||||
/// @param line_id
|
/// @param line_id Index of the block the cache node to remove starts at.
|
||||||
/// @return
|
/// @return Returns true if this node has no more live childs, false if
|
||||||
|
/// there is a least one line child.
|
||||||
///
|
///
|
||||||
|
/// Iterates the child nodes, calls the method recursively on all live
|
||||||
|
/// nodes, deletes any node returning true, and counts number of nodes
|
||||||
|
/// still alive, returning true if any are alive.
|
||||||
bool KillLine(unsigned long line_id)
|
bool KillLine(unsigned long line_id)
|
||||||
{
|
{
|
||||||
int sub_caches_left = 0;
|
int sub_caches_left = 0;
|
||||||
|
@ -416,13 +411,15 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief Constructor.
|
||||||
/// @param _provider
|
/// @param _provider Audio provider to pass to child nodes.
|
||||||
/// @param _start
|
/// @param _start Index of first block to manage.
|
||||||
/// @param _length
|
/// @param _length Number of blocks to manage.
|
||||||
/// @param _overlaps
|
/// @param _overlaps Number of lines per block.
|
||||||
/// @param _depth
|
/// @param _depth Number of levels in the tree above this node.
|
||||||
///
|
///
|
||||||
|
/// Determine how many sub-caches are required, how big they
|
||||||
|
/// should be and allocates memory to store their pointers.
|
||||||
IntermediateSpectrumCache(AudioProvider *_provider, unsigned long _start, unsigned long _length, unsigned int _overlaps, int _depth)
|
IntermediateSpectrumCache(AudioProvider *_provider, unsigned long _start, unsigned long _length, unsigned int _overlaps, int _depth)
|
||||||
{
|
{
|
||||||
provider = _provider;
|
provider = _provider;
|
||||||
|
@ -446,8 +443,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief Destructor, deletes all still-live sub caches.
|
||||||
///
|
|
||||||
virtual ~IntermediateSpectrumCache()
|
virtual ~IntermediateSpectrumCache()
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < sub_caches.size(); ++i)
|
for (size_t i = 0; i < sub_caches.size(); ++i)
|
||||||
|
@ -460,35 +456,32 @@ public:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
/// @class AudioSpectrumCacheManager
|
/// @class AudioSpectrumCacheManager
|
||||||
/// @brief DOCME
|
/// @brief Manages a frequency-power cache tree.
|
||||||
///
|
///
|
||||||
/// DOCME
|
/// The primary task of this class is to manage the amount of memory consumed by
|
||||||
|
/// the cache and delete items when it grows too large.
|
||||||
class AudioSpectrumCacheManager {
|
class AudioSpectrumCacheManager {
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/// DOCME
|
/// Root node of the cache tree.
|
||||||
IntermediateSpectrumCache *cache_root;
|
IntermediateSpectrumCache *cache_root;
|
||||||
|
|
||||||
/// DOCME
|
unsigned long cache_hits, ///< Number of times the cache was used to retrieve data
|
||||||
|
cache_misses; ///< Number of times data had to be calculated
|
||||||
|
|
||||||
/// DOCME
|
/// Current time, used for cache aging purposes.
|
||||||
unsigned long cache_hits, cache_misses;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
AudioSpectrumCache::CacheAccessTime cur_time;
|
AudioSpectrumCache::CacheAccessTime cur_time;
|
||||||
|
|
||||||
|
/// Maximum number of lines to keep in cache.
|
||||||
/// DOCME
|
|
||||||
unsigned long max_lines_cached;
|
unsigned long max_lines_cached;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief Wrapper around cache tree, to get frequency-power data
|
||||||
/// @param i
|
/// @param i Block to get data from.
|
||||||
/// @param overlap
|
/// @param overlap Line in block to get data from.
|
||||||
/// @return
|
/// @return Returns a reference to the requested line.
|
||||||
///
|
///
|
||||||
AudioSpectrumCache::CacheLine &GetLine(unsigned long i, unsigned int overlap)
|
AudioSpectrumCache::CacheLine &GetLine(unsigned long i, unsigned int overlap)
|
||||||
{
|
{
|
||||||
|
@ -502,9 +495,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief Remove old data from the cache.
|
||||||
/// @return
|
|
||||||
///
|
///
|
||||||
|
/// Ages the cache by finding the least recently accessed data and removing cache data
|
||||||
|
/// until the total number of lines stored in the tree is less than the maximum.
|
||||||
void Age()
|
void Age()
|
||||||
{
|
{
|
||||||
wxLogDebug(_T("AudioSpectrumCacheManager stats: hits=%u, misses=%u, misses%%=%f, managed lines=%u (max=%u)"), cache_hits, cache_misses, cache_misses/float(cache_hits+cache_misses)*100, cache_root->GetManagedLineCount(), max_lines_cached);
|
wxLogDebug(_T("AudioSpectrumCacheManager stats: hits=%u, misses=%u, misses%%=%f, managed lines=%u (max=%u)"), cache_hits, cache_misses, cache_misses/float(cache_hits+cache_misses)*100, cache_root->GetManagedLineCount(), max_lines_cached);
|
||||||
|
@ -551,12 +545,14 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief Constructor
|
||||||
/// @param provider
|
/// @param provider Audio provider to pass to cache tree nodes.
|
||||||
/// @param line_length
|
/// @param line_length Number of audio samples to use per block.
|
||||||
/// @param num_lines
|
/// @param num_lines Number of blocks to produce in total from the audio.
|
||||||
/// @param num_overlaps
|
/// @param num_overlaps Number of overlaps per block.
|
||||||
///
|
///
|
||||||
|
/// Initialises the cache tree root and calculates the maximum number of cache lines
|
||||||
|
/// to keep based on the Audio Spectrum Memory Max configuration setting.
|
||||||
AudioSpectrumCacheManager(AudioProvider *provider, unsigned long line_length, unsigned long num_lines, unsigned int num_overlaps)
|
AudioSpectrumCacheManager(AudioProvider *provider, unsigned long line_length, unsigned long num_lines, unsigned int num_overlaps)
|
||||||
{
|
{
|
||||||
cache_hits = cache_misses = 0;
|
cache_hits = cache_misses = 0;
|
||||||
|
@ -573,8 +569,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
/// @brief Destructor, deletes the cache tree root node.
|
||||||
///
|
|
||||||
~AudioSpectrumCacheManager()
|
~AudioSpectrumCacheManager()
|
||||||
{
|
{
|
||||||
delete cache_root;
|
delete cache_root;
|
||||||
|
@ -582,12 +577,9 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// AudioSpectrum
|
// AudioSpectrum, documented in .h file
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
|
||||||
/// @param _provider
|
|
||||||
///
|
|
||||||
AudioSpectrum::AudioSpectrum(AudioProvider *_provider)
|
AudioSpectrum::AudioSpectrum(AudioProvider *_provider)
|
||||||
{
|
{
|
||||||
provider = _provider;
|
provider = _provider;
|
||||||
|
@ -677,26 +669,12 @@ AudioSpectrum::AudioSpectrum(AudioProvider *_provider)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
|
||||||
///
|
|
||||||
AudioSpectrum::~AudioSpectrum()
|
AudioSpectrum::~AudioSpectrum()
|
||||||
{
|
{
|
||||||
delete cache;
|
delete cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
|
||||||
/// @param range_start
|
|
||||||
/// @param range_end
|
|
||||||
/// @param selected
|
|
||||||
/// @param img
|
|
||||||
/// @param imgleft
|
|
||||||
/// @param imgwidth
|
|
||||||
/// @param imgpitch
|
|
||||||
/// @param imgheight
|
|
||||||
///
|
|
||||||
void AudioSpectrum::RenderRange(int64_t range_start, int64_t range_end, bool selected, unsigned char *img, int imgleft, int imgwidth, int imgpitch, int imgheight)
|
void AudioSpectrum::RenderRange(int64_t range_start, int64_t range_end, bool selected, unsigned char *img, int imgleft, int imgwidth, int imgpitch, int imgheight)
|
||||||
{
|
{
|
||||||
unsigned long first_line = (unsigned long)(fft_overlaps * range_start / line_length / 2);
|
unsigned long first_line = (unsigned long)(fft_overlaps * range_start / line_length / 2);
|
||||||
|
@ -746,8 +724,7 @@ void AudioSpectrum::RenderRange(int64_t range_start, int64_t range_end, bool sel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @internal Macro that stores pixel data, depends on local variables in AudioSpectrum::RenderRange
|
||||||
/// DOCME
|
|
||||||
#define WRITE_PIXEL \
|
#define WRITE_PIXEL \
|
||||||
if (intensity < 0) intensity = 0; \
|
if (intensity < 0) intensity = 0; \
|
||||||
if (intensity > 255) intensity = 255; \
|
if (intensity > 255) intensity = 255; \
|
||||||
|
@ -796,8 +773,7 @@ void AudioSpectrum::RenderRange(int64_t range_start, int64_t range_end, bool sel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @internal The WRITE_PIXEL macro is only defined inside AudioSpectrum::RenderRange
|
||||||
/// DOCME
|
|
||||||
#undef WRITE_PIXEL
|
#undef WRITE_PIXEL
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -808,10 +784,6 @@ void AudioSpectrum::RenderRange(int64_t range_start, int64_t range_end, bool sel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief DOCME
|
|
||||||
/// @param _power_scale
|
|
||||||
///
|
|
||||||
void AudioSpectrum::SetScaling(float _power_scale)
|
void AudioSpectrum::SetScaling(float _power_scale)
|
||||||
{
|
{
|
||||||
power_scale = _power_scale;
|
power_scale = _power_scale;
|
||||||
|
|
|
@ -34,10 +34,12 @@
|
||||||
/// @see audio_spectrum.cpp
|
/// @see audio_spectrum.cpp
|
||||||
/// @ingroup audio_ui
|
/// @ingroup audio_ui
|
||||||
///
|
///
|
||||||
|
/// Calculate and render a frequency-power spectrum for PCM audio data.
|
||||||
|
|
||||||
|
|
||||||
#ifndef AUDIO_SPECTRUM_H
|
#ifndef AUDIO_SPECTRUM_H
|
||||||
|
|
||||||
/// DOCME
|
/// Include guard for audio_spectrum.h
|
||||||
#define AUDIO_SPECTRUM_H
|
#define AUDIO_SPECTRUM_H
|
||||||
|
|
||||||
#include <wx/wxprec.h>
|
#include <wx/wxprec.h>
|
||||||
|
@ -49,54 +51,60 @@
|
||||||
class AudioSpectrumCacheManager;
|
class AudioSpectrumCacheManager;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
/// @class AudioSpectrum
|
/// @class AudioSpectrum
|
||||||
/// @brief DOCME
|
/// @brief Render frequency-power spectrum graphs for audio data.
|
||||||
///
|
///
|
||||||
/// DOCME
|
/// Renders frequency-power spectrum graphs of PCM audio data using a fast fourier transform
|
||||||
|
/// to derive the data. The frequency-power data are cached to avoid re-computing them
|
||||||
|
/// frequently, and the cache size is limited by a configuration setting.
|
||||||
|
///
|
||||||
|
/// The spectrum image is rendered to a 32 bit RGB bitmap. Power data is scaled linearly
|
||||||
|
/// and not logarithmically, since the rendering is done with limited precision, but
|
||||||
|
/// an amplification factor can be specified to see different ranges.
|
||||||
class AudioSpectrum {
|
class AudioSpectrum {
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/// DOCME
|
/// Internal cache management for the spectrum
|
||||||
AudioSpectrumCacheManager *cache;
|
AudioSpectrumCacheManager *cache;
|
||||||
|
|
||||||
|
/// Colour table used for regular rendering
|
||||||
/// DOCME
|
|
||||||
unsigned char colours_normal[256*3];
|
unsigned char colours_normal[256*3];
|
||||||
|
|
||||||
/// DOCME
|
/// Colour table used for rendering the audio selection
|
||||||
unsigned char colours_selected[256*3];
|
unsigned char colours_selected[256*3];
|
||||||
|
|
||||||
|
/// The audio provider to use as source
|
||||||
/// DOCME
|
|
||||||
AudioProvider *provider;
|
AudioProvider *provider;
|
||||||
|
|
||||||
|
unsigned long line_length; ///< Number of frequency components per line (half of number of samples)
|
||||||
/// DOCME
|
unsigned long num_lines; ///< Number of lines needed for the audio
|
||||||
unsigned long line_length; // number of frequency components per line (half of number of samples)
|
unsigned int fft_overlaps; ///< Number of overlaps used in FFT
|
||||||
|
float power_scale; ///< Amplification of displayed power
|
||||||
/// DOCME
|
int minband; ///< Smallest frequency band displayed
|
||||||
unsigned long num_lines; // number of lines needed for the audio
|
int maxband; ///< Largest frequency band displayed
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
unsigned int fft_overlaps; // number of overlaps used in FFT
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
float power_scale; // amplification of displayed power
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
int minband; // smallest frequency band displayed
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
int maxband; // largest frequency band displayed
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/// @brief Constructor
|
||||||
|
/// @param _provider Audio provider to render spectrum data for.
|
||||||
|
///
|
||||||
|
/// Reads configuration data for the spectrum display and initialises itself following that.
|
||||||
AudioSpectrum(AudioProvider *_provider);
|
AudioSpectrum(AudioProvider *_provider);
|
||||||
|
/// @brief Destructor
|
||||||
~AudioSpectrum();
|
~AudioSpectrum();
|
||||||
|
|
||||||
|
/// @brief Render a range of audio spectrum to a bitmap buffer.
|
||||||
|
/// @param range_start First audio sample in the range to render.
|
||||||
|
/// @param range_end Last audio sample in the range to render.
|
||||||
|
/// @param selected Use the alternate colour palette?
|
||||||
|
/// @param img Pointer to 32 bit RGBX data
|
||||||
|
/// @param imgleft Offset from left edge of bitmap to render to, in pixels
|
||||||
|
/// @param imgwidth Width of bitmap to render, in pixels
|
||||||
|
/// @param imgpitch Offset from one scanline to the next in the bitmap, in bytes
|
||||||
|
/// @param imgheight Number of lines in the bitmap
|
||||||
void RenderRange(int64_t range_start, int64_t range_end, bool selected, unsigned char *img, int imgleft, int imgwidth, int imgpitch, int imgheight);
|
void RenderRange(int64_t range_start, int64_t range_end, bool selected, unsigned char *img, int imgleft, int imgwidth, int imgpitch, int imgheight);
|
||||||
|
|
||||||
|
/// @brief Set the amplification to use when rendering.
|
||||||
|
/// @param _power_scale Amplification factor to use.
|
||||||
void SetScaling(float _power_scale);
|
void SetScaling(float _power_scale);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue