mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-02-03 03:21:00 +00:00
added libraries: opus flac libsndfile updated: libvorbis libogg openal - Everything works as expected for now. Bare in mind libsndfile needed the check for whether or not it could find the xiph libraries removed in order for this to work.
267 lines
6.6 KiB
C
267 lines
6.6 KiB
C
/*
|
|
** Copyright (C) 2008-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
|
|
** Copyright (C) 2012 IOhannes m zmoelnig, IEM <zmoelnig@iem.at>
|
|
**
|
|
** This program is free software; you can redistribute it and/or modify
|
|
** it under the terms of the GNU Lesser General Public License as published by
|
|
** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
|
|
**
|
|
** You should have received a copy of the GNU Lesser General Public License
|
|
** along with this program; if not, write to the Free Software
|
|
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include "sfconfig.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "sndfile.h"
|
|
#include "sfendian.h"
|
|
#include "common.h"
|
|
|
|
static int64_t
|
|
hash_of_str (const char * str)
|
|
{ int64_t marker = 0 ;
|
|
int k ;
|
|
|
|
for (k = 0 ; str [k] ; k++)
|
|
marker = marker * 0x7f + ((const uint8_t *) str) [k] ;
|
|
|
|
return marker ;
|
|
} /* hash_of_str */
|
|
|
|
SF_CHUNK_ITERATOR *
|
|
psf_get_chunk_iterator (SF_PRIVATE * psf, const char * marker_str)
|
|
{ const READ_CHUNKS * pchk = &psf->rchunks ;
|
|
int idx ;
|
|
|
|
if (marker_str)
|
|
idx = psf_find_read_chunk_str (pchk, marker_str) ;
|
|
else
|
|
idx = pchk->used > 0 ? 0 : -1 ;
|
|
|
|
if (idx < 0)
|
|
return NULL ;
|
|
|
|
if (psf->iterator == NULL)
|
|
{ psf->iterator = calloc (1, sizeof (SF_CHUNK_ITERATOR)) ;
|
|
if (psf->iterator == NULL)
|
|
return NULL ;
|
|
} ;
|
|
|
|
psf->iterator->sndfile = (SNDFILE *) psf ;
|
|
|
|
if (marker_str)
|
|
{ int64_t hash ;
|
|
size_t marker_len ;
|
|
union
|
|
{ uint32_t marker ;
|
|
char str [5] ;
|
|
} u ;
|
|
|
|
snprintf (u.str, sizeof (u.str), "%s", marker_str) ;
|
|
|
|
marker_len = strlen (marker_str) ;
|
|
if (marker_len > 64)
|
|
marker_len = 64 ;
|
|
|
|
hash = marker_len > 4 ? hash_of_str (marker_str) : u.marker ;
|
|
|
|
memcpy (psf->iterator->id, marker_str, marker_len) ;
|
|
psf->iterator->id_size = (unsigned) marker_len ;
|
|
psf->iterator->hash = hash ;
|
|
}
|
|
|
|
psf->iterator->current = idx ;
|
|
|
|
return psf->iterator ;
|
|
} /* psf_get_chunk_iterator */
|
|
|
|
SF_CHUNK_ITERATOR *
|
|
psf_next_chunk_iterator (const READ_CHUNKS * pchk , SF_CHUNK_ITERATOR * iterator)
|
|
{ uint64_t hash = iterator->hash ;
|
|
uint32_t k ;
|
|
|
|
iterator->current++ ;
|
|
|
|
if (hash)
|
|
{ for (k = iterator->current ; k < pchk->used ; k++)
|
|
if (pchk->chunks [k].hash == hash)
|
|
{ iterator->current = k ;
|
|
return iterator ;
|
|
}
|
|
}
|
|
else if (iterator->current < pchk->used)
|
|
return iterator ;
|
|
|
|
/* No match, clear iterator and return NULL */
|
|
memset (iterator, 0, sizeof (*iterator)) ;
|
|
return NULL ;
|
|
} /* psf_next_chunk_iterator */
|
|
|
|
static int
|
|
psf_store_read_chunk (READ_CHUNKS * pchk, const READ_CHUNK * rchunk)
|
|
{ if (pchk->count == 0)
|
|
{ pchk->used = 0 ;
|
|
pchk->count = 20 ;
|
|
pchk->chunks = calloc (pchk->count, sizeof (READ_CHUNK)) ;
|
|
if (!pchk->chunks)
|
|
{ return SFE_MALLOC_FAILED ;
|
|
} ;
|
|
}
|
|
else if (pchk->used > pchk->count)
|
|
return SFE_INTERNAL ;
|
|
else if (pchk->used == pchk->count)
|
|
{ READ_CHUNK * old_ptr = pchk->chunks ;
|
|
int new_count = 3 * (pchk->count + 1) / 2 ;
|
|
|
|
READ_CHUNK * new_chunks = realloc (old_ptr, new_count * sizeof (READ_CHUNK)) ;
|
|
if (new_chunks == NULL)
|
|
{
|
|
return SFE_MALLOC_FAILED ;
|
|
} else {
|
|
pchk->chunks = new_chunks;
|
|
} ;
|
|
pchk->count = new_count ;
|
|
} ;
|
|
|
|
pchk->chunks [pchk->used] = *rchunk ;
|
|
|
|
pchk->used ++ ;
|
|
|
|
return SFE_NO_ERROR ;
|
|
} /* psf_store_read_chunk */
|
|
|
|
int
|
|
psf_store_read_chunk_u32 (READ_CHUNKS * pchk, uint32_t marker, sf_count_t offset, uint32_t len)
|
|
{ READ_CHUNK rchunk ;
|
|
|
|
memset (&rchunk, 0, sizeof (rchunk)) ;
|
|
|
|
rchunk.hash = marker ;
|
|
rchunk.mark32 = marker ;
|
|
rchunk.offset = offset ;
|
|
rchunk.len = len ;
|
|
|
|
rchunk.id_size = 4 ;
|
|
memcpy (rchunk.id, &marker, rchunk.id_size) ;
|
|
|
|
return psf_store_read_chunk (pchk, &rchunk) ;
|
|
} /* psf_store_read_chunk_u32 */
|
|
|
|
int
|
|
psf_find_read_chunk_str (const READ_CHUNKS * pchk, const char * marker_str)
|
|
{ uint64_t hash ;
|
|
uint32_t k ;
|
|
union
|
|
{ uint32_t marker ;
|
|
char str [5] ;
|
|
} u ;
|
|
|
|
snprintf (u.str, sizeof (u.str), "%s", marker_str) ;
|
|
|
|
hash = strlen (marker_str) > 4 ? hash_of_str (marker_str) : u.marker ;
|
|
|
|
for (k = 0 ; k < pchk->used ; k++)
|
|
if (pchk->chunks [k].hash == hash)
|
|
return k ;
|
|
|
|
return -1 ;
|
|
} /* psf_find_read_chunk_str */
|
|
|
|
int
|
|
psf_find_read_chunk_m32 (const READ_CHUNKS * pchk, uint32_t marker)
|
|
{ uint32_t k ;
|
|
|
|
for (k = 0 ; k < pchk->used ; k++)
|
|
if (pchk->chunks [k].mark32 == marker)
|
|
return k ;
|
|
|
|
return -1 ;
|
|
} /* psf_find_read_chunk_m32 */
|
|
int
|
|
psf_find_read_chunk_iterator (const READ_CHUNKS * pchk, const SF_CHUNK_ITERATOR * marker)
|
|
{ if (marker->current < pchk->used)
|
|
return marker->current ;
|
|
|
|
return -1 ;
|
|
} /* psf_find_read_chunk_iterator */
|
|
|
|
int
|
|
psf_store_read_chunk_str (READ_CHUNKS * pchk, const char * marker_str, sf_count_t offset, uint32_t len)
|
|
{ READ_CHUNK rchunk ;
|
|
union
|
|
{ uint32_t marker ;
|
|
char str [5] ;
|
|
} u ;
|
|
size_t marker_len ;
|
|
|
|
memset (&rchunk, 0, sizeof (rchunk)) ;
|
|
snprintf (u.str, sizeof (u.str), "%s", marker_str) ;
|
|
|
|
marker_len = strlen (marker_str) ;
|
|
|
|
rchunk.hash = marker_len > 4 ? hash_of_str (marker_str) : u.marker ;
|
|
rchunk.mark32 = u.marker ;
|
|
rchunk.offset = offset ;
|
|
rchunk.len = len ;
|
|
|
|
rchunk.id_size = marker_len > 64 ? 64 : (unsigned) marker_len ;
|
|
memcpy (rchunk.id, marker_str, rchunk.id_size) ;
|
|
|
|
return psf_store_read_chunk (pchk, &rchunk) ;
|
|
} /* psf_store_read_chunk_str */
|
|
|
|
int
|
|
psf_save_write_chunk (WRITE_CHUNKS * pchk, const SF_CHUNK_INFO * chunk_info)
|
|
{ union
|
|
{ uint32_t marker ;
|
|
char str [5] ;
|
|
/* Update snprintf() format string below when changing this */
|
|
} u ;
|
|
uint32_t len ;
|
|
|
|
if (pchk->count == 0)
|
|
{ pchk->used = 0 ;
|
|
pchk->count = 20 ;
|
|
pchk->chunks = calloc (pchk->count, sizeof (WRITE_CHUNK)) ;
|
|
if (!pchk->chunks)
|
|
{ return SFE_MALLOC_FAILED ;
|
|
} ;
|
|
}
|
|
else if (pchk->used >= pchk->count)
|
|
{ WRITE_CHUNK * old_ptr = pchk->chunks ;
|
|
int new_count = 3 * (pchk->count + 1) / 2 ;
|
|
|
|
WRITE_CHUNK * new_chunks = realloc (old_ptr, new_count * sizeof (WRITE_CHUNK)) ;
|
|
if (new_chunks == NULL)
|
|
{
|
|
return SFE_MALLOC_FAILED ;
|
|
} else {
|
|
pchk->chunks = new_chunks;
|
|
} ;
|
|
} ;
|
|
|
|
len = chunk_info->datalen ;
|
|
while (len & 3) len ++ ;
|
|
|
|
snprintf (u.str, sizeof (u.str), "%.4s", chunk_info->id) ;
|
|
|
|
pchk->chunks [pchk->used].hash = strlen (chunk_info->id) > 4 ? hash_of_str (chunk_info->id) : u.marker ;
|
|
pchk->chunks [pchk->used].mark32 = u.marker ;
|
|
pchk->chunks [pchk->used].len = len ;
|
|
pchk->chunks [pchk->used].data = psf_memdup (chunk_info->data, chunk_info->datalen) ;
|
|
|
|
pchk->used ++ ;
|
|
|
|
return SFE_NO_ERROR ;
|
|
} /* psf_save_write_chunk */
|
|
|