#include #include #include #include #include #include #define CHUNK_DEFAULT (0x1000) #define MIN(a, b) (a < b? a : b) #define MAX(a, b) (a > b? a : b) int usage(const char* progname) { fprintf(stderr, "usage: %s [-c chunk] <-s size | -u size>\n", progname); return 1; } int main(int argc, char** argv) { int optch; int cflag = 0; const char* carg = NULL; enum { INV = -1, INT, UINT } tflag = INV; const char* sizearg = NULL; while ((optch = getopt(argc, argv, "c:s:u:h")) != -1) { switch (optch) { case 'c': cflag = 1; carg = optarg; break; case 's': tflag = INT; sizearg = optarg; break; case 'u': tflag = UINT; sizearg = optarg; break; case 'h': default: return usage(*argv); } } if (tflag == INV) return usage(*argv); size_t membsize = strtoull(sizearg, NULL, 10); size_t chunk = cflag? strtoull(carg, NULL, 10) : CHUNK_DEFAULT; uint8_t* intbuffer = aligned_alloc(0x40, chunk * membsize); float* floatbuffer = aligned_alloc(0x40, chunk * sizeof(float)); size_t rd; if (intbuffer == NULL || floatbuffer == NULL) err(1, "malloc()"); while ((rd = fread(intbuffer, membsize, chunk, stdin))) { for (size_t i = 0; i < rd; ++i) { void* p = &intbuffer[i * membsize]; switch (tflag) { case INT: switch (membsize) { case 1: floatbuffer[i] = (float)*(int8_t*)p; break; case 2: floatbuffer[i] = (float)*(int16_t*)p; break; case 4: floatbuffer[i] = (float)*(int32_t*)p; break; case 8: floatbuffer[i] = (float)*(int64_t*)p; break; default: errx(1, "invalid size"); } break; case UINT: switch (membsize) { case 1: floatbuffer[i] = (float)*(int8_t*)p; break; case 2: floatbuffer[i] = (float)*(int16_t*)p; break; case 4: floatbuffer[i] = (float)*(int32_t*)p; break; case 8: floatbuffer[i] = (float)*(int64_t*)p; break; default: errx(1, "invalid size"); } break; default: errx(1, "invalid type"); } } fwrite(floatbuffer, sizeof(float), rd, stdout); } return 0; }