2009-09-17 13:08:33 +00:00
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
/*
2012-09-09 16:57:42 +01:00
Rubber Band Library
2009-09-17 13:08:33 +00:00
An audio time - stretching and pitch - shifting library .
2018-03-07 13:10:19 +00:00
Copyright 2007 - 2018 Particular Programs Ltd .
2012-09-09 16:57:42 +01:00
2009-09-17 13:08:33 +00:00
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 2 of the
License , or ( at your option ) any later version . See the file
COPYING included with this distribution for more information .
2012-09-09 16:57:42 +01:00
Alternatively , if you have a valid commercial licence for the
Rubber Band Library obtained by agreement with the copyright
holders , you may redistribute and / or modify it under the terms
described in that licence .
If you wish to distribute code using the Rubber Band Library
under terms other than those of the GNU General Public License ,
you must obtain a valid commercial licence before doing so .
2009-09-17 13:08:33 +00:00
*/
# ifndef _RUBBERBAND_ALLOCATORS_H_
# define _RUBBERBAND_ALLOCATORS_H_
# include "VectorOps.h"
# include <new> // for std::bad_alloc
# include <stdlib.h>
# ifndef HAVE_POSIX_MEMALIGN
# ifndef _WIN32
# ifndef __APPLE__
# ifndef LACK_POSIX_MEMALIGN
# define HAVE_POSIX_MEMALIGN
# endif
# endif
# endif
# endif
2018-11-29 09:12:59 +00:00
# ifndef MALLOC_IS_ALIGNED
# ifndef MALLOC_IS_NOT_ALIGNED
# ifdef __APPLE__
# define MALLOC_IS_ALIGNED
# endif
# endif
# endif
# ifndef HAVE__ALIGNED_MALLOC
# ifndef LACK__ALIGNED_MALLOC
# ifdef _WIN32
# define HAVE__ALIGNED_MALLOC
# endif
# endif
# endif
2009-09-17 13:08:33 +00:00
# ifdef HAVE_POSIX_MEMALIGN
# include <sys/mman.h>
2018-11-29 09:12:59 +00:00
# include <errno.h>
2009-09-17 13:08:33 +00:00
# endif
2012-09-09 16:57:42 +01:00
# ifdef LACK_BAD_ALLOC
namespace std { struct bad_alloc { } ; }
# endif
2011-11-25 11:11:59 +00:00
2009-09-17 13:08:33 +00:00
namespace RubberBand {
template < typename T >
T * allocate ( size_t count )
{
void * ptr = 0 ;
2018-11-29 09:12:59 +00:00
// We'd like to check HAVE_IPP first and, if it's defined, call
// ippsMalloc_8u(count * sizeof(T)). But that isn't a general
// replacement for malloc() because it only takes an int
// argument. So we save it for the specialisations of
// allocate<float> and allocate<double> below, where we're more
// likely to get away with it.
# ifdef MALLOC_IS_ALIGNED
ptr = malloc ( count * sizeof ( T ) ) ;
# else /* !MALLOC_IS_ALIGNED */
// That's the "sufficiently aligned" functions dealt with, the
// rest need a specific alignment provided to the call. 32-byte
// alignment is required for at least OpenMAX
2012-09-09 16:57:42 +01:00
static const int alignment = 32 ;
2018-11-29 09:12:59 +00:00
# ifdef HAVE__ALIGNED_MALLOC
ptr = _aligned_malloc ( count * sizeof ( T ) , alignment ) ;
# else /* !HAVE__ALIGNED_MALLOC */
# ifdef HAVE_POSIX_MEMALIGN
int rv = posix_memalign ( & ptr , alignment , count * sizeof ( T ) ) ;
if ( rv ) {
# ifndef NO_EXCEPTIONS
if ( rv = = EINVAL ) {
throw std : : logic_error ( " Internal error: invalid alignment " ) ;
} else {
throw std : : bad_alloc ( ) ;
}
# else
abort ( ) ;
# endif
}
# else /* !HAVE_POSIX_MEMALIGN */
2012-09-09 16:57:42 +01:00
# ifdef USE_OWN_ALIGNED_MALLOC
2018-11-29 09:12:59 +00:00
# pragma message("Rolling own aligned malloc: this is unlikely to perform as well as the alternatives")
2012-09-09 16:57:42 +01:00
// Alignment must be a power of two, bigger than the pointer
// size. Stuff the actual malloc'd pointer in just before the
// returned value. This is the least desirable way to do this --
// the other options below are all better
size_t allocd = count * sizeof ( T ) + alignment ;
void * buf = malloc ( allocd ) ;
if ( buf ) {
char * adj = ( char * ) buf ;
while ( ( unsigned long long ) adj & ( alignment - 1 ) ) - - adj ;
ptr = ( ( char * ) adj ) + alignment ;
2018-11-29 09:12:59 +00:00
new ( ( ( void * * ) ptr ) [ - 1 ] ) ( void * ) ;
2012-09-09 16:57:42 +01:00
( ( void * * ) ptr ) [ - 1 ] = buf ;
}
2018-11-29 09:12:59 +00:00
2012-09-09 16:57:42 +01:00
# else /* !USE_OWN_ALIGNED_MALLOC */
2018-11-29 09:12:59 +00:00
# error "No aligned malloc available: define MALLOC_IS_ALIGNED to use system malloc, HAVE_POSIX_MEMALIGN if posix_memalign is available, HAVE__ALIGNED_MALLOC if _aligned_malloc is available, or USE_OWN_ALIGNED_MALLOC to roll our own"
2012-09-09 16:57:42 +01:00
# endif /* !USE_OWN_ALIGNED_MALLOC */
2018-11-29 09:12:59 +00:00
# endif /* !HAVE_POSIX_MEMALIGN */
# endif /* !HAVE__ALIGNED_MALLOC */
# endif /* !MALLOC_IS_ALIGNED */
2011-11-25 11:11:59 +00:00
if ( ! ptr ) {
2012-09-09 16:57:42 +01:00
# ifndef NO_EXCEPTIONS
2018-11-29 09:12:59 +00:00
throw std : : bad_alloc ( ) ;
2012-09-09 16:57:42 +01:00
# else
abort ( ) ;
# endif
2011-11-25 11:11:59 +00:00
}
2018-11-29 09:12:59 +00:00
T * typed_ptr = static_cast < T * > ( ptr ) ;
for ( size_t i = 0 ; i < count ; + + i ) {
new ( typed_ptr + i ) T ;
}
return typed_ptr ;
2009-09-17 13:08:33 +00:00
}
2012-09-09 16:57:42 +01:00
# ifdef HAVE_IPP
template < >
float * allocate ( size_t count ) ;
template < >
double * allocate ( size_t count ) ;
# endif
2009-09-17 13:08:33 +00:00
template < typename T >
T * allocate_and_zero ( size_t count )
{
T * ptr = allocate < T > ( count ) ;
v_zero ( ptr , count ) ;
return ptr ;
}
template < typename T >
void deallocate ( T * ptr )
{
2018-11-29 09:12:59 +00:00
if ( ! ptr ) return ;
# ifdef MALLOC_IS_ALIGNED
free ( ( void * ) ptr ) ;
# else /* !MALLOC_IS_ALIGNED */
# ifdef HAVE__ALIGNED_MALLOC
_aligned_free ( ( void * ) ptr ) ;
# else /* !HAVE__ALIGNED_MALLOC */
# ifdef HAVE_POSIX_MEMALIGN
free ( ( void * ) ptr ) ;
# else /* !HAVE_POSIX_MEMALIGN */
2012-09-09 16:57:42 +01:00
# ifdef USE_OWN_ALIGNED_MALLOC
2018-11-29 09:12:59 +00:00
free ( ( ( void * * ) ptr ) [ - 1 ] ) ;
2012-09-09 16:57:42 +01:00
# else /* !USE_OWN_ALIGNED_MALLOC */
2018-11-29 09:12:59 +00:00
# error "No aligned malloc available: define MALLOC_IS_ALIGNED to use system malloc, HAVE_POSIX_MEMALIGN if posix_memalign is available, or USE_OWN_ALIGNED_MALLOC to roll our own"
2012-09-09 16:57:42 +01:00
# endif /* !USE_OWN_ALIGNED_MALLOC */
2018-11-29 09:12:59 +00:00
# endif /* !HAVE_POSIX_MEMALIGN */
# endif /* !HAVE__ALIGNED_MALLOC */
# endif /* !MALLOC_IS_ALIGNED */
2009-09-17 13:08:33 +00:00
}
2012-09-09 16:57:42 +01:00
# ifdef HAVE_IPP
template < >
void deallocate ( float * ) ;
template < >
void deallocate ( double * ) ;
# endif
2011-03-19 12:41:38 +00:00
/// Reallocate preserving contents but leaving additional memory uninitialised
2009-09-17 13:08:33 +00:00
template < typename T >
T * reallocate ( T * ptr , size_t oldcount , size_t count )
{
2011-11-25 11:11:59 +00:00
T * newptr = allocate < T > ( count ) ;
2009-09-17 13:08:33 +00:00
if ( oldcount & & ptr ) {
v_copy ( newptr , ptr , oldcount < count ? oldcount : count ) ;
}
if ( ptr ) deallocate < T > ( ptr ) ;
return newptr ;
}
2011-03-19 12:41:38 +00:00
/// Reallocate, zeroing all contents
2011-01-07 21:46:36 +00:00
template < typename T >
T * reallocate_and_zero ( T * ptr , size_t oldcount , size_t count )
{
ptr = reallocate ( ptr , oldcount , count ) ;
v_zero ( ptr , count ) ;
return ptr ;
}
2011-03-19 12:41:38 +00:00
/// Reallocate preserving contents and zeroing any additional memory
template < typename T >
T * reallocate_and_zero_extension ( T * ptr , size_t oldcount , size_t count )
{
ptr = reallocate ( ptr , oldcount , count ) ;
if ( count > oldcount ) v_zero ( ptr + oldcount , count - oldcount ) ;
return ptr ;
}
2009-09-17 13:08:33 +00:00
template < typename T >
T * * allocate_channels ( size_t channels , size_t count )
{
T * * ptr = allocate < T * > ( channels ) ;
for ( size_t c = 0 ; c < channels ; + + c ) {
ptr [ c ] = allocate < T > ( count ) ;
}
return ptr ;
}
template < typename T >
T * * allocate_and_zero_channels ( size_t channels , size_t count )
{
T * * ptr = allocate < T * > ( channels ) ;
for ( size_t c = 0 ; c < channels ; + + c ) {
ptr [ c ] = allocate_and_zero < T > ( count ) ;
}
return ptr ;
}
template < typename T >
void deallocate_channels ( T * * ptr , size_t channels )
{
if ( ! ptr ) return ;
for ( size_t c = 0 ; c < channels ; + + c ) {
deallocate < T > ( ptr [ c ] ) ;
}
deallocate < T * > ( ptr ) ;
}
template < typename T >
T * * reallocate_channels ( T * * ptr ,
size_t oldchannels , size_t oldcount ,
size_t channels , size_t count )
{
2011-11-25 11:11:59 +00:00
T * * newptr = allocate_channels < T > ( channels , count ) ;
2009-09-17 13:08:33 +00:00
if ( oldcount & & ptr ) {
v_copy_channels ( newptr , ptr , channels , oldcount < count ? oldcount : count ) ;
}
2010-03-24 09:44:51 +00:00
if ( ptr ) deallocate_channels < T > ( ptr , channels ) ;
return newptr ;
}
template < typename T >
T * * reallocate_and_zero_extend_channels ( T * * ptr ,
size_t oldchannels , size_t oldcount ,
size_t channels , size_t count )
{
2011-11-25 11:11:59 +00:00
T * * newptr = allocate_and_zero_channels < T > ( channels , count ) ;
2010-03-24 09:44:51 +00:00
if ( oldcount & & ptr ) {
v_copy_channels ( newptr , ptr , channels , oldcount < count ? oldcount : count ) ;
}
if ( ptr ) deallocate_channels < T > ( ptr , channels ) ;
2009-09-17 13:08:33 +00:00
return newptr ;
}
2012-09-09 16:57:42 +01:00
/// RAII class to call deallocate() on destruction
template < typename T >
class Deallocator
{
public :
Deallocator ( T * t ) : m_t ( t ) { }
~ Deallocator ( ) { deallocate < T > ( m_t ) ; }
private :
T * m_t ;
} ;
2009-09-17 13:08:33 +00:00
}
# endif