2008-01-31 07:04:26 +01:00
|
|
|
#include <string.h>
|
|
|
|
#include "util.h"
|
2008-02-04 11:34:18 +01:00
|
|
|
#include "streamtypes.h"
|
2008-01-31 07:04:26 +01:00
|
|
|
|
2018-06-30 17:35:07 +02:00
|
|
|
const char * filename_extension(const char * pathname) {
|
|
|
|
const char * filename;
|
|
|
|
const char * extension;
|
2008-01-31 07:04:26 +01:00
|
|
|
|
2019-02-23 17:47:19 +01:00
|
|
|
/* favor strrchr (optimized/aligned) rather than homemade loops */
|
|
|
|
|
|
|
|
/* find possible separator first to avoid misdetecting folders with dots + extensionless files
|
|
|
|
* (allow both slashes as plugin could pass normalized '/') */
|
|
|
|
filename = strrchr(pathname, '/');
|
|
|
|
if (filename != NULL)
|
|
|
|
filename++; /* skip separator */
|
|
|
|
else {
|
|
|
|
filename = strrchr(pathname, '\\');
|
|
|
|
if (filename != NULL)
|
|
|
|
filename++; /* skip separator */
|
|
|
|
else
|
|
|
|
filename = pathname; /* pathname has no separators (single filename) */
|
|
|
|
}
|
2008-01-31 07:04:26 +01:00
|
|
|
|
2018-06-30 17:35:07 +02:00
|
|
|
extension = strrchr(filename,'.');
|
2019-02-23 17:47:19 +01:00
|
|
|
if (extension != NULL)
|
|
|
|
extension++; /* skip dot */
|
2018-06-30 17:35:07 +02:00
|
|
|
else
|
2019-02-23 17:47:19 +01:00
|
|
|
extension = filename + strlen(filename); /* point to null (empty "" string for extensionless files) */
|
2018-06-30 17:35:07 +02:00
|
|
|
|
|
|
|
return extension;
|
2008-01-31 07:04:26 +01:00
|
|
|
}
|
|
|
|
|
2017-10-28 01:34:32 +02:00
|
|
|
/* unused */
|
|
|
|
/*
|
2019-03-02 19:23:37 +01:00
|
|
|
void interleave_channel(sample_t * outbuffer, sample_t * inbuffer, int32_t sample_count, int channel_count, int channel_number) {
|
2008-01-31 07:04:26 +01:00
|
|
|
int32_t insample,outsample;
|
|
|
|
|
|
|
|
if (channel_count==1) {
|
|
|
|
memcpy(outbuffer,inbuffer,sizeof(sample)*sample_count);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (insample=0,outsample=channel_number;insample<sample_count;insample++,outsample+=channel_count) {
|
|
|
|
outbuffer[outsample]=inbuffer[insample];
|
|
|
|
}
|
|
|
|
}
|
2017-10-28 01:34:32 +02:00
|
|
|
*/
|
2008-01-31 07:04:26 +01:00
|
|
|
|
|
|
|
/* failed attempt at interleave in place */
|
|
|
|
/*
|
2019-03-02 19:23:37 +01:00
|
|
|
void interleave_stereo(sample_t * buffer, int32_t sample_count) {
|
2008-01-31 07:04:26 +01:00
|
|
|
int32_t tomove, belongs;
|
2019-03-02 19:23:37 +01:00
|
|
|
sample_t moving,temp;
|
2008-01-31 07:04:26 +01:00
|
|
|
|
|
|
|
tomove = sample_count;
|
|
|
|
moving = buffer[tomove];
|
|
|
|
|
|
|
|
do {
|
|
|
|
if (tomove<sample_count)
|
|
|
|
belongs = tomove*2;
|
|
|
|
else
|
|
|
|
belongs = (tomove-sample_count)*2+1;
|
|
|
|
|
|
|
|
temp = buffer[belongs];
|
|
|
|
buffer[belongs] = moving;
|
|
|
|
moving = temp;
|
|
|
|
|
|
|
|
tomove = belongs;
|
|
|
|
} while (tomove != sample_count);
|
|
|
|
}
|
|
|
|
*/
|
2008-02-04 11:34:18 +01:00
|
|
|
|
2016-12-18 12:46:11 +01:00
|
|
|
void put_8bit(uint8_t * buf, int8_t i) {
|
|
|
|
buf[0] = i;
|
|
|
|
}
|
|
|
|
|
2008-02-04 11:34:18 +01:00
|
|
|
void put_16bitLE(uint8_t * buf, int16_t i) {
|
2008-05-20 17:18:38 +02:00
|
|
|
buf[0] = (i & 0xFF);
|
2008-02-04 11:34:18 +01:00
|
|
|
buf[1] = i >> 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
void put_32bitLE(uint8_t * buf, int32_t i) {
|
2008-05-20 17:18:38 +02:00
|
|
|
buf[0] = (uint8_t)(i & 0xFF);
|
|
|
|
buf[1] = (uint8_t)((i >> 8) & 0xFF);
|
|
|
|
buf[2] = (uint8_t)((i >> 16) & 0xFF);
|
|
|
|
buf[3] = (uint8_t)((i >> 24) & 0xFF);
|
2008-02-04 11:34:18 +01:00
|
|
|
}
|
|
|
|
|
2009-03-16 16:45:02 +01:00
|
|
|
void put_16bitBE(uint8_t * buf, int16_t i) {
|
|
|
|
buf[0] = i >> 8;
|
|
|
|
buf[1] = (i & 0xFF);
|
|
|
|
}
|
|
|
|
|
|
|
|
void put_32bitBE(uint8_t * buf, int32_t i) {
|
|
|
|
buf[0] = (uint8_t)((i >> 24) & 0xFF);
|
|
|
|
buf[1] = (uint8_t)((i >> 16) & 0xFF);
|
|
|
|
buf[2] = (uint8_t)((i >> 8) & 0xFF);
|
|
|
|
buf[3] = (uint8_t)(i & 0xFF);
|
|
|
|
}
|
|
|
|
|
2020-06-04 23:11:38 +02:00
|
|
|
int round10(int val) {
|
|
|
|
int round_val = val % 10;
|
|
|
|
if (round_val < 5) /* half-down rounding */
|
|
|
|
return val - round_val;
|
|
|
|
else
|
|
|
|
return val + (10 - round_val);
|
|
|
|
}
|
|
|
|
|
2019-03-02 19:23:37 +01:00
|
|
|
void swap_samples_le(sample_t *buf, int count) {
|
2019-09-29 20:09:28 +02:00
|
|
|
/* Windows can't be BE... I think */
|
|
|
|
#if !defined(_WIN32)
|
|
|
|
#if !defined(__BYTE_ORDER__) || __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
|
2010-08-31 06:44:04 +02:00
|
|
|
int i;
|
2019-03-02 19:23:37 +01:00
|
|
|
for (i = 0; i < count; i++) {
|
2019-09-29 20:09:28 +02:00
|
|
|
/* 16b sample in memory: aabb where aa=MSB, bb=LSB */
|
2019-03-02 19:23:37 +01:00
|
|
|
uint8_t b0 = buf[i] & 0xff;
|
|
|
|
uint8_t b1 = buf[i] >> 8;
|
2010-08-31 06:44:04 +02:00
|
|
|
uint8_t *p = (uint8_t*)&(buf[i]);
|
2019-09-29 20:09:28 +02:00
|
|
|
/* 16b sample in buffer: bbaa where bb=LSB, aa=MSB */
|
2010-08-31 06:44:04 +02:00
|
|
|
p[0] = b0;
|
|
|
|
p[1] = b1;
|
2019-09-29 20:09:28 +02:00
|
|
|
/* when endianness is LE, buffer has bbaa already so this function can be skipped */
|
2010-08-31 06:44:04 +02:00
|
|
|
}
|
2019-09-29 20:09:28 +02:00
|
|
|
#endif
|
|
|
|
#endif
|
2010-08-31 06:44:04 +02:00
|
|
|
}
|
|
|
|
|
2008-03-11 02:27:59 +01:00
|
|
|
/* length is maximum length of dst. dst will always be null-terminated if
|
|
|
|
* length > 0 */
|
|
|
|
void concatn(int length, char * dst, const char * src) {
|
|
|
|
int i,j;
|
|
|
|
if (length <= 0) return;
|
|
|
|
for (i=0;i<length-1 && dst[i];i++); /* find end of dst */
|
|
|
|
for (j=0;i<length-1 && src[j];i++,j++)
|
|
|
|
dst[i]=src[j];
|
|
|
|
dst[i]='\0';
|
|
|
|
}
|