experimental support for MMX/SSE/SSE2 instructions

git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@1832 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
Tobias Doerffel
2008-11-10 10:31:11 +00:00
parent 986fce1126
commit 22dc97f13d
34 changed files with 3198 additions and 283 deletions

View File

@@ -121,31 +121,22 @@ public:
protected:
// subclasses can re-implement this for being used in conjunction with
// processNextBuffer()
virtual void writeBuffer( const surroundSampleFrame * /* _buf*/,
virtual void writeBuffer( const sampleFrameA * /* _buf*/,
const fpp_t /*_frames*/,
const float /*_master_gain*/ )
{
}
// called by according driver for fetching new sound-data
fpp_t getNextBuffer( surroundSampleFrame * _ab );
// convert a given audio-buffer to a buffer in signed 16-bit samples
// returns num of bytes in outbuf
Uint32 convertToS16( const surroundSampleFrame * _ab,
const fpp_t _frames,
const float _master_gain,
int_sample_t * _output_buffer,
const bool _convert_endian = FALSE );
fpp_t getNextBuffer( sampleFrameA * _ab );
// clear given signed-int-16-buffer
void clearS16Buffer( int_sample_t * _outbuf,
const fpp_t _frames );
void clearS16Buffer( intSampleFrameA * _outbuf, const fpp_t _frames );
// resample given buffer from samplerate _src_sr to samplerate _dst_sr
void resample( const surroundSampleFrame * _src,
void resample( const sampleFrameA * _src,
const fpp_t _frames,
surroundSampleFrame * _dst,
sampleFrameA * _dst,
const sample_rate_t _src_sr,
const sample_rate_t _dst_sr );
@@ -161,9 +152,11 @@ protected:
bool hqAudio( void ) const;
protected:
bool m_supportsCapture;
private:
sample_rate_t m_sampleRate;
ch_cnt_t m_channels;
@@ -175,7 +168,7 @@ private:
SRC_DATA m_srcData;
SRC_STATE * m_srcState;
surroundSampleFrame * m_buffer;
sampleFrameA * m_buffer;
} ;

View File

@@ -27,6 +27,7 @@
#define _AUDIO_DUMMY_H
#include "audio_device.h"
#include "basic_ops.h"
#include "micro_timer.h"
@@ -94,16 +95,16 @@ private:
virtual void run( void )
{
microTimer timer;
while( TRUE )
while( true )
{
timer.reset();
const surroundSampleFrame * b =
surroundSampleFrame * b =
getMixer()->nextBuffer();
if( !b )
{
break;
}
delete[] b;
alignedFreeFrames( b );
const Sint32 microseconds = static_cast<Sint32>(
getMixer()->framesPerPeriod() *

View File

@@ -94,7 +94,7 @@ private:
QSemaphore m_stop_semaphore;
QVector<jack_port_t *> m_outputPorts;
surroundSampleFrame * m_outBuf;
sampleFrameA * m_outBuf;
f_cnt_t m_framesDoneInCurBuf;

View File

@@ -40,14 +40,14 @@ public:
audioPort( const QString & _name, bool _has_effect_chain = true );
~audioPort();
inline sampleFrame * firstBuffer( void )
inline sampleFrameA * firstBuffer( void )
{
return( m_firstBuffer );
return m_firstBuffer;
}
inline sampleFrame * secondBuffer( void )
inline sampleFrameA * secondBuffer( void )
{
return( m_secondBuffer );
return m_secondBuffer;
}
inline void lockFirstBuffer( void )
@@ -76,7 +76,7 @@ public:
// indicate whether JACK & Co should provide output-buffer at ext. port
inline bool extOutputEnabled( void ) const
{
return( m_extOutputEnabled );
return m_extOutputEnabled;
}
void setExtOutputEnabled( bool _enabled );
@@ -86,12 +86,12 @@ public:
// (-1 = none 0 = master)
inline fx_ch_t nextFxChannel( void ) const
{
return( m_nextFxChannel );
return m_nextFxChannel;
}
inline effectChain * getEffects( void )
{
return( m_effects );
return m_effects;
}
void setNextFxChannel( const fx_ch_t _chnl )
@@ -102,7 +102,7 @@ public:
const QString & name( void ) const
{
return( m_name );
return m_name;
}
void setName( const QString & _new_name );
@@ -122,8 +122,8 @@ public:
private:
volatile bufferUsages m_bufferUsage;
sampleFrame * m_firstBuffer;
sampleFrame * m_secondBuffer;
sampleFrameA * m_firstBuffer;
sampleFrameA * m_secondBuffer;
QMutex m_firstBufferLock;
QMutex m_secondBufferLock;

View File

@@ -140,7 +140,7 @@ private:
bool m_wasPAInitError;
surroundSampleFrame * m_outBuf;
sampleFrameA * m_outBuf;
int m_outBufPos;
int m_outBufSize;

View File

@@ -76,8 +76,8 @@ private:
SDL_AudioSpec m_audioHandle;
surroundSampleFrame * m_outBuf;
Uint8 * m_convertedBuf;
sampleFrameA * m_outBuf;
intSampleFrameA * m_convertedBuf;
int m_convertedBufPos;
int m_convertedBufSize;

94
include/basic_ops.h Normal file
View File

@@ -0,0 +1,94 @@
/*
* basic_ops.h - basic memory operations
*
* Copyright (c) 2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
* 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.
*
* 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 (see COPYING); if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
*/
#ifndef _BASIC_OPS_H
#define _BASIC_OPS_H
#include "lmms_basics.h"
#ifdef LMMS_HAVE_STDBOOL_H
#include <stdbool.h>
#endif
void initBasicOps( void );
void * alignedMalloc( int _bytes );
void alignedFree( void * _buf );
sampleFrameA * alignedAllocFrames( int _frames );
void alignedFreeFrames( sampleFrameA * _buf );
// all aligned* functions assume data to be 16 byte aligned and size to be
// multiples of 64
typedef void (*alignedMemCpyFunc)( void * RP _dst, const void * RP _src,
int _size );
typedef void (*alignedMemClearFunc)( void * RP _dst, int _size );
typedef void (*alignedBufApplyGainFunc)( sampleFrameA * RP _dst,
float _gain, int _frames );
typedef void (*alignedBufMixFunc)( sampleFrameA * RP _dst,
const sampleFrameA * RP _src,
int _frames );
typedef void (*alignedBufMixLRCoeffFunc)( sampleFrameA * RP _dst,
const sampleFrameA * RP _src,
float _left, float _right,
int _frames );
typedef void (*unalignedBufMixLRCoeffFunc)( sampleFrame * RP _dst,
const sampleFrame * RP _src,
float _left, float _right,
int _frames );
typedef void (*alignedBufWetDryMixFunc)( sampleFrameA * RP _dst,
const sampleFrameA * RP _src,
float _wet, float _dry, int _frames );
typedef void (*alignedBufWetDryMixSplittedFunc)( sampleFrameA * RP _dst,
const float * RP _left,
const float * RP _right,
float _wet, float _dry, int _frames );
typedef int (*alignedConvertToS16Func)( const sampleFrameA * RP _src,
intSampleFrameA * RP _dst,
const fpp_t _frames,
const float _master_gain,
const bool _convert_endian );
extern alignedMemCpyFunc alignedMemCpy;
extern alignedMemClearFunc alignedMemClear;
extern alignedBufApplyGainFunc alignedBufApplyGain;
extern alignedBufMixFunc alignedBufMix;
extern alignedBufMixLRCoeffFunc alignedBufMixLRCoeff;
extern unalignedBufMixLRCoeffFunc unalignedBufMixLRCoeff;
extern alignedBufWetDryMixFunc alignedBufWetDryMix;
extern alignedBufWetDryMixSplittedFunc alignedBufWetDryMixSplitted;
extern alignedConvertToS16Func alignedConvertToS16;
#ifdef LMMS_HOST_X86
#define X86_OPTIMIZATIONS
#endif
#ifdef LMMS_HOST_X86_64
#define X86_OPTIMIZATIONS
#endif
#endif

View File

@@ -2,6 +2,7 @@
* fifo_buffer.h - FIFO fixed-size buffer
*
* Copyright (c) 2007 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
* Copyright (c) 2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
*
@@ -33,50 +34,50 @@ class fifoBuffer
{
public:
fifoBuffer( int _size ) :
m_reader_sem( _size ),
m_writer_sem( _size ),
m_reader_index( 0 ),
m_writer_index( 0 ),
m_readerSem( _size ),
m_writerSem( _size ),
m_readerIndex( 0 ),
m_writerIndex( 0 ),
m_size( _size )
{
m_buffer = new T[_size];
m_reader_sem.acquire( _size );
m_readerSem.acquire( _size );
}
~fifoBuffer()
{
delete[] m_buffer;
m_reader_sem.release( m_size );
m_readerSem.release( m_size );
}
void write( T _element )
{
m_writer_sem.acquire();
m_buffer[m_writer_index++] = _element;
m_writer_index %= m_size;
m_reader_sem.release();
m_writerSem.acquire();
m_buffer[m_writerIndex++] = _element;
m_writerIndex %= m_size;
m_readerSem.release();
}
T read( void )
{
m_reader_sem.acquire();
T element = m_buffer[m_reader_index++];
m_reader_index %= m_size;
m_writer_sem.release();
return( element );
m_readerSem.acquire();
T element = m_buffer[m_readerIndex++];
m_readerIndex %= m_size;
m_writerSem.release();
return element;
}
bool available( void )
{
return( m_reader_sem.available() );
return m_readerSem.available();
}
private:
QSemaphore m_reader_sem;
QSemaphore m_writer_sem;
int m_reader_index;
int m_writer_index;
QSemaphore m_readerSem;
QSemaphore m_writerSem;
int m_readerIndex;
int m_writerIndex;
int m_size;
T * m_buffer;

View File

@@ -1,5 +1,5 @@
/*
* types.h - typedefs for common types that are used in the whole app
* lmms_basics.h - common basics for the whole App
*
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
*
@@ -23,10 +23,8 @@
*/
#ifndef _TYPES_H
#define _TYPES_H
#include <limits>
#ifndef _LMMS_BASICS_H
#define _LMMS_BASICS_H
#include "lmmsconfig.h"
@@ -68,6 +66,9 @@ typedef Uint32 jo_id_t; // (unique) ID of a journalling object
#define likely(x) __builtin_expect((x),1)
#define unlikely(x) __builtin_expect((x),0)
#ifdef __cplusplus
#include <limits>
template<typename T>
struct typeInfo
@@ -115,25 +116,50 @@ inline bool typeInfo<float>::isEqual( float _x, float _y )
return absVal( _x - _y ) < minEps();
}
#endif
const ch_cnt_t DEFAULT_CHANNELS = 2;
const ch_cnt_t SURROUND_CHANNELS =
#define DEFAULT_CHANNELS 2
#define LMMS_DISABLE_SURROUND
#ifndef LMMS_DISABLE_SURROUND
4;
#ifdef LMMS_DISABLE_SURROUND
#define SURROUND_CHANNELS 2
#else
2;
#define SURROUND_CHANNELS 4
#endif
typedef sample_t sampleFrame[DEFAULT_CHANNELS];
typedef sample_t surroundSampleFrame[SURROUND_CHANNELS];
#define ALIGN_SIZE 16
#if __GNUC__
typedef sample_t sampleFrameA[DEFAULT_CHANNELS] __attribute__((__aligned__(ALIGN_SIZE)));
typedef int_sample_t intSampleFrameA[DEFAULT_CHANNELS] __attribute__((__aligned__(ALIGN_SIZE)));
#define RP __restrict__
#else
#define RP
#endif
#ifdef __cplusplus
const int BYTES_PER_SAMPLE = sizeof( sample_t );
const int BYTES_PER_INT_SAMPLE = sizeof( int_sample_t );
const int BYTES_PER_FRAME = sizeof( sampleFrame );
const int BYTES_PER_SURROUND_FRAME = sizeof( surroundSampleFrame );
const float OUTPUT_SAMPLE_MULTIPLIER = 32767.0f;
#else
#define BYTES_PER_SAMPLE sizeof( sample_t )
#define BYTES_PER_INT_SAMPLE sizeof( int_sample_t )
#define BYTES_PER_FRAME sizeof( sampleFrame )
#define BYTES_PER_SURROUND_FRAME sizeof( surroundSampleFrame )
#define OUTPUT_SAMPLE_MULTIPLIER 32767.0f
#endif

View File

@@ -57,13 +57,6 @@ class audioPort;
const fpp_t DEFAULT_BUFFER_SIZE = 256;
const int BYTES_PER_SAMPLE = sizeof( sample_t );
const int BYTES_PER_INT_SAMPLE = sizeof( int_sample_t );
const int BYTES_PER_FRAME = sizeof( sampleFrame );
const int BYTES_PER_SURROUND_FRAME = sizeof( surroundSampleFrame );
const float OUTPUT_SAMPLE_MULTIPLIER = 32767.0f;
const float BaseFreq = 440.0f;
const Keys BaseKey = Key_A;
@@ -361,7 +354,7 @@ public:
return m_inputBufferFrames[ m_inputBufferRead ];
}
inline const surroundSampleFrame * nextBuffer( void )
inline surroundSampleFrame * nextBuffer( void )
{
return hasFifoWriter() ? m_fifo->read() : renderNextBuffer();
}
@@ -407,7 +400,7 @@ private:
midiClient * tryMidiClients( void );
const surroundSampleFrame * renderNextBuffer( void );
surroundSampleFrame * renderNextBuffer( void );