Ho riscontrato un problema con un metodo SSE che sto scrivendo che esegue l'elaborazione audio. Ho implementato una funzione casuale SSE basato su carta Intel qui:Gli intrinseci SSE causano il normale funzionamento float per restituire -1. # INV
Ho anche un metodo che esegue conversioni da Mobile a S16 utilizzando SSE inoltre, la conversione viene eseguita semplicemente come segue:
unsigned int Float_S16LE(float *data, const unsigned int samples, uint8_t *dest)
{
int16_t *dst = (int16_t*)dest;
const __m128 mul = _mm_set_ps1((float)INT16_MAX);
__m128 rand;
const uint32_t even = count & ~0x3;
for(uint32_t i = 0; i < even; i += 4, data += 4, dst += 4)
{
/* random round to dither */
FloatRand4(-0.5f, 0.5f, NULL, &rand);
__m128 rmul = _mm_add_ps(mul, rand);
__m128 in = _mm_mul_ps(_mm_load_ps(data),rmul);
__m64 con = _mm_cvtps_pi16(in);
memcpy(dst, &con, sizeof(int16_t) * 4);
}
}
FloatRand4 è definito come segue:
static inline void FloatRand4(const float min, const float max, float result[4], __m128 *sseresult = NULL)
{
const float delta = (max - min)/2.0f;
const float factor = delta/(float)INT32_MAX;
...
}
Se sseresult != NULL
il 01.236.142,623251 millions Il risultatoviene restituito e result
non viene utilizzato. Ciò si esegue perfettamente sul primo ciclo, ma sul ciclo successivo delta
diventa -1.#INF
anziché 1.0
. Se commento la riga __m64 con = _mm_cvtps_pi16(in);
il problema scompare.
Penso che la FPU stia entrando in uno stato sconosciuto o qualcosa del genere.
_mm_cvtps_pi16 è una cattiva idea. Usa una combinazione di _mm_cvtps_epi32, _mm_packs_epi32 e _mm_store_si128/_mm_storeu_si128 per convertire 8 float in 8 int16_t e il tuo problema è scomparso! –