Update of /cvsroot/pure-data/pd/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv935
Modified Files: Tag: devel_0_37 s_audio_asio.cpp Log Message: some improvements
Index: s_audio_asio.cpp =================================================================== RCS file: /cvsroot/pure-data/pd/src/Attic/s_audio_asio.cpp,v retrieving revision 1.1.2.3 retrieving revision 1.1.2.4 diff -C2 -d -r1.1.2.3 -r1.1.2.4 *** s_audio_asio.cpp 4 Nov 2004 23:28:25 -0000 1.1.2.3 --- s_audio_asio.cpp 6 Nov 2004 15:22:38 -0000 1.1.2.4 *************** *** 24,27 **** --- 24,34 ---- #include "stdio.h" /* for sprintf */
+ /* fast float to integer conversion adapted from Erik de Castro Lopo */ + #define _ISOC9X_SOURCE 1 + #define _ISOC99_SOURCE 1 + #define __USE_ISOC9X 1 + #define __USE_ISOC99 1 + #include "math.h" + #define ASIODEBUG
*************** *** 43,53 **** ASIOBool directprocess);
! /* sample converting helper functions: ! * - global send / receive functions ! * - sample conversion functions (adapted from ASIOConvertSamples.cpp */ ! void asio_convert_and_send (t_sample* source, void* dest, ! ASIOSampleType format, long asio_bufsize); ! void asio_convert_and_receive (void* source, t_sample* dest, ! ASIOSampleType format, long asio_bufsize); void float32toInt16(float* inbuffer, void* outbuffer, long frames); void Int16tofloat32(void* inbuffer, float* outbuffer, long frames); --- 50,54 ---- ASIOBool directprocess);
! void float32copy(float* inbuffer, float* outbuffer, long frames); void float32toInt16(float* inbuffer, void* outbuffer, long frames); void Int16tofloat32(void* inbuffer, float* outbuffer, long frames); *************** *** 56,59 **** --- 57,84 ---- void float32toInt32(float* inbuffer, void* outbuffer, long frames); void Int32tofloat32(void* inbuffer, float* outbuffer, long frames); + void float32toInt16_S(float* inbuffer, void* outbuffer, long frames); + void Int16tofloat32_S(void* inbuffer, float* outbuffer, long frames); + void float32toInt24_S(float* inbuffer, void* outbuffer, long frames); + void Int24tofloat32_S(void* inbuffer, float* outbuffer, long frames); + void float32toInt32_S(float* inbuffer, void* outbuffer, long frames); + void Int32tofloat32_S(void* inbuffer, float* outbuffer, long frames); + + /* Swap LSB to MSB and vice versa */ + #define SwapLong(v) ((((v)>>24)&0xFF)|(((v)>>8)&0xFF00)|(((v)&0xFF00)<<8)|(((v)&0xFF)<<24)) ; + #define SwapShort(v) ((((v)>>8)&0xFF)|(((v)&0xFF)<<8)) ; + + typedef void converter_out_t(float* inbuffer, void* outbuffer, long frames); + typedef void converter_in_t(void* inbuffer, float* outbuffer, long frames); + + /* sample converting helper functions: + * - global send / receive functions + * - sample conversion functions (adapted from ASIOConvertSamples.cpp */ + void *asio_converter_send (ASIOSampleType format); + void *asio_converter_receive (ASIOSampleType format); + + /* pointers to the converter functions of each channel are stored here */ + static void **asio_converter = NULL; + +
/* some local helper functions */ *************** *** 267,277 **** }
! for (i = 0; i != sys_inchannels + sys_outchannels; ++i) { asio_channelinfo[i].channel = asio_bufferinfo[i].channelNum; asio_channelinfo[i].isInput = asio_bufferinfo[i].isInput; ASIOGetChannelInfo(&asio_channelinfo[i]); - }
/* get latencies */ --- 292,308 ---- }
! asio_converter = (void **)getbytes(channels * sizeof (void *)); ! ! for (i = 0; i != sys_outchannels + sys_inchannels; ++i) { asio_channelinfo[i].channel = asio_bufferinfo[i].channelNum; asio_channelinfo[i].isInput = asio_bufferinfo[i].isInput; ASIOGetChannelInfo(&asio_channelinfo[i]);
+ if (i < sys_outchannels) + asio_converter[i] = asio_converter_send(asio_channelinfo[i].type); + else + asio_converter[i] = asio_converter_receive(asio_channelinfo[i].type); + }
/* get latencies */ *************** *** 330,334 **** { ASIOError status; ! int channels = asio_inchannels + asio_outchannels; int i;
--- 361,365 ---- { ASIOError status; ! int channels = sys_inchannels + sys_outchannels; int i;
*************** *** 350,353 **** --- 381,387 ---- asio_channelinfo = NULL; + if(asio_converter) freebytes(asio_converter, channels * sizeof (void *)); + asio_converter = NULL; + ASIOExit(); freebytes(asio_driver, sizeof (ASIODriverInfo)); *************** *** 482,500 **** * todo: improve input latency */ ! for (i = 0; i < asio_outchannels + asio_inchannels; i++) { if (asio_bufferinfo[i].isInput != ASIOTrue) { ! asio_convert_and_send(asio_ringbuffer[i]+asio_ringbuffer_outoffset, ! (void*) asio_bufferinfo[i].buffers[db_idx], ! asio_channelinfo[i].type, asio_bufsize); } else /* these are the input channels */ { ! asio_convert_and_receive((void*)asio_bufferinfo[i].buffers[db_idx], ! asio_ringbuffer[i]+asio_ringbuffer_outoffset, ! asio_channelinfo[i].type, asio_bufsize); } - } pthread_cond_broadcast(&asio_ringbuf_cond); --- 516,535 ---- * todo: improve input latency */ ! ! for (i = 0; i < sys_outchannels + sys_inchannels; i++) { + if(asio_converter[i]) if (asio_bufferinfo[i].isInput != ASIOTrue) { ! ((converter_out_t *)asio_converter[i])(asio_ringbuffer[i]+asio_ringbuffer_outoffset, ! (void*) asio_bufferinfo[i].buffers[db_idx], ! asio_bufsize); } else /* these are the input channels */ { ! ((converter_in_t *)asio_converter[i])((void*)asio_bufferinfo[i].buffers[db_idx], ! asio_ringbuffer[i]+asio_ringbuffer_outoffset, ! asio_bufsize); } } pthread_cond_broadcast(&asio_ringbuf_cond); *************** *** 524,528 ****
/* sample converting helper functions */ ! void asio_convert_and_send(t_sample* source, void* dest, ASIOSampleType format, long bufsize) {
--- 559,563 ----
/* sample converting helper functions */ ! void *asio_converter_send(ASIOSampleType format) {
*************** *** 533,548 **** { case ASIOSTInt16LSB: ! /* e.g. m audio quattro */ ! float32toInt16(source, dest, bufsize); ! break; case ASIOSTFloat32LSB: // IEEE 754 32 bit float, as found on Intel x86 architecture ! memcpy (dest, source, bufsize * sizeof (float)); /* check */ ! break; case ASIOSTInt24LSB: // used for 20 bits as well ! float32toInt24(source, dest, bufsize); ! break; case ASIOSTInt32LSB: ! float32toInt32(source, dest, bufsize); ! break;
case ASIOSTFloat64LSB: // IEEE 754 64 bit double float, as found on Intel x86 architecture --- 568,585 ---- { case ASIOSTInt16LSB: ! return float32toInt16; case ASIOSTFloat32LSB: // IEEE 754 32 bit float, as found on Intel x86 architecture ! return float32copy; case ASIOSTInt24LSB: // used for 20 bits as well ! return float32toInt24; case ASIOSTInt32LSB: ! return float32toInt32; ! ! case ASIOSTInt16MSB: ! return float32toInt16_S; ! case ASIOSTInt24MSB: // used for 20 bits as well ! return float32toInt24_S; ! case ASIOSTInt32MSB: ! return float32toInt32_S;
case ASIOSTFloat64LSB: // IEEE 754 64 bit double float, as found on Intel x86 architecture *************** *** 555,564 **** case ASIOSTInt32LSB24: // 32 bit data with 24 bit alignment
- case ASIOSTInt16MSB: - - case ASIOSTInt24MSB: // used for 20 bits as well - - case ASIOSTInt32MSB: - case ASIOSTFloat32MSB: // IEEE 754 32 bit float, as found on Intel x86 architecture
--- 592,595 ---- *************** *** 570,584 **** case ASIOSTInt32MSB20: // 32 bit data with 20 bit alignment case ASIOSTInt32MSB24: // 32 bit data with 24 bit alignment ! { ! static int written = 0; ! if(written < 3) { ! post("Output sample Type %d not supported, yet!!!",format); ! ++written; ! } ! } } }
! void asio_convert_and_receive (void* source, t_sample* dest, ASIOSampleType format, long bufsize) { #ifdef ASIODEBUG --- 601,611 ---- case ASIOSTInt32MSB20: // 32 bit data with 20 bit alignment case ASIOSTInt32MSB24: // 32 bit data with 24 bit alignment ! default: ! post("Output sample Type %d not supported, yet!!!",format); ! return NULL; } }
! void *asio_converter_receive (ASIOSampleType format) { #ifdef ASIODEBUG *************** *** 589,603 **** { case ASIOSTInt16LSB: ! Int16tofloat32(source, dest, bufsize); ! break; case ASIOSTFloat32LSB: // IEEE 754 32 bit float, as found on Intel x86 architecture ! memcpy (dest, source, bufsize * sizeof (float)); /* check */ ! break; case ASIOSTInt24LSB: // used for 20 bits as well ! Int24tofloat32(source, dest, bufsize); ! break; case ASIOSTInt32LSB: ! Int32tofloat32(source, dest, bufsize); ! break;
case ASIOSTFloat64LSB: // IEEE 754 64 bit double float, as found on Intel x86 architecture --- 616,633 ---- { case ASIOSTInt16LSB: ! return Int16tofloat32; case ASIOSTFloat32LSB: // IEEE 754 32 bit float, as found on Intel x86 architecture ! return float32copy; case ASIOSTInt24LSB: // used for 20 bits as well ! return Int24tofloat32; case ASIOSTInt32LSB: ! return Int32tofloat32; ! ! case ASIOSTInt16MSB: ! return Int16tofloat32_S; ! case ASIOSTInt24MSB: // used for 20 bits as well ! return Int24tofloat32_S; ! case ASIOSTInt32MSB: ! return Int32tofloat32_S;
case ASIOSTFloat64LSB: // IEEE 754 64 bit double float, as found on Intel x86 architecture *************** *** 610,616 **** case ASIOSTInt32LSB24: // 32 bit data with 24 bit alignment
- case ASIOSTInt16MSB: - case ASIOSTInt24MSB: // used for 20 bits as well - case ASIOSTInt32MSB: case ASIOSTFloat32MSB: // IEEE 754 32 bit float, as found on Intel x86 architecture case ASIOSTFloat64MSB: // IEEE 754 64 bit double float, as found on Intel x86 architecture --- 640,643 ---- *************** *** 622,632 **** case ASIOSTInt32MSB20: // 32 bit data with 20 bit alignment case ASIOSTInt32MSB24: // 32 bit data with 24 bit alignment ! { ! static int written = 0; ! if(written < 3) { post("Input sample Type %d not supported, yet!!!",format); ! ++written; ! } ! } }
--- 649,655 ---- case ASIOSTInt32MSB20: // 32 bit data with 20 bit alignment case ASIOSTInt32MSB24: // 32 bit data with 24 bit alignment ! default: post("Input sample Type %d not supported, yet!!!",format); ! return NULL; }
*************** *** 639,642 **** --- 662,670 ---- #define SCALE_INT32 2147483647.f /* (- (expt 2 31) 1) */
+ void float32copy(float* inbuffer, float* outbuffer, long frames) + { + memcpy (outbuffer, inbuffer, frames* sizeof (float)); /* check */ + } + void float32toInt16(float* inbuffer, void* outbuffer, long frames) { *************** *** 644,648 **** while (frames--) { ! *out++ = (short)(*inbuffer++ * SCALE_INT16); } } --- 672,687 ---- while (frames--) { ! float o = (*inbuffer++ * SCALE_INT16); ! #ifdef __GNUC__ ! *out++ = (short)lrintf(o); ! #else ! short srt; ! __asm ! { ! fld o ! fistp srt ! }; ! *out++ = srt; ! #endif } } *************** *** 662,666 **** while (frames--) { ! *out++ = (int)(*inbuffer * SCALE_INT24); } } --- 701,716 ---- while (frames--) { ! float o = (*inbuffer * SCALE_INT24); ! #ifdef __GNUC__ ! *out++ = (int)lrintf(o); ! #else ! int intg; ! __asm ! { ! fld o ! fistp intg ! }; ! *out++ = intg; ! #endif } } *************** *** 680,684 **** while (frames--) { ! *out++ = (long)(*inbuffer * SCALE_INT32); } } --- 730,745 ---- while (frames--) { ! float o = (*inbuffer * SCALE_INT32); ! #ifdef __GNUC__ ! *out++ = lrintf(o); ! #else ! long lng; ! __asm ! { ! fld o ! fistp lng ! }; ! *out++ = lng; ! #endif } } *************** *** 693,696 **** --- 754,869 ---- }
+ void float32toInt16_S(float* inbuffer, void* outbuffer, long frames) + { + char* out = (char*)outbuffer; + while (frames--) + { + float o = (*inbuffer++ * SCALE_INT16); + #ifdef __GNUC__ + short reverse = (short)lrintf(o); + #else + short reverse; + __asm + { + fld o + fistp reverse + }; + #endif + out[1] = ((char *)&reverse)[0]; + out[0] = ((char *)&reverse)[1]; + out += 2; + } + } + + void Int16tofloat32_S(void* inbuffer, float* outbuffer, long frames) + { + char* in = (char*)inbuffer; + short d; + while (frames--) + { + ((char *)&d)[0] = in[1]; + ((char *)&d)[1] = in[0]; + *outbuffer++ = (float)(d * (1.f / SCALE_INT16)); + in += 2; + } + } + + void float32toInt24_S(float* inbuffer, void* outbuffer, long frames) + { + char* out = (char*)outbuffer; + while (frames--) + { + int o = (*inbuffer * SCALE_INT24); + #ifdef __GNUC__ + int reverse = (int)lrintf(o); + #else + int reverse; + __asm + { + fld o + fistp reverse + }; + #endif + out[2] = ((char *)&reverse)[0]; + out[1] = ((char *)&reverse)[1]; + out[0] = ((char *)&reverse)[2]; + out += 3; + } + } + + void Int24tofloat32_S(void* inbuffer, float* outbuffer, long frames) + { + char* in = (char*)inbuffer; + long d = 0; + while (frames--) + { + ((char *)&d)[1] = in[2]; + ((char *)&d)[2] = in[1]; + ((char *)&d)[3] = in[0]; + *outbuffer++ = (float)(d * (1.f / SCALE_INT24)); + in += 3; + } + } + + void float32toInt32_S(float* inbuffer, void* outbuffer, long frames) + { + char* out = (char*)outbuffer; + while (frames--) + { + float o = (*inbuffer * SCALE_INT32); + #ifdef __GNUC__ + long reverse = (long)lrintf(o); + #else + long reverse; + __asm + { + fld o + fistp reverse + }; + #endif + out[3] = ((char *)&reverse)[0]; + out[2] = ((char *)&reverse)[1]; + out[1] = ((char *)&reverse)[2]; + out[0] = ((char *)&reverse)[3]; + out += 4; + } + } + + void Int32tofloat32_S(void* inbuffer, float* outbuffer, long frames) + { + char* in = (char*)inbuffer; + long d; + while (frames--) + { + ((char *)&d)[0] = in[3]; + ((char *)&d)[1] = in[2]; + ((char *)&d)[2] = in[1]; + ((char *)&d)[3] = in[0]; + *outbuffer++ = (float)(d * (1.f / SCALE_INT32)); + in += 3; + } + } + + /* some local helper functions */ inline void prepare_asio_drivernames(void)