-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
sound_convert sample type conversions
wav_file simple wave file utility fix basename misspelling in nsfplay/makefile fix basename missing in cmd/makefile
- Loading branch information
1 parent
cc8cf32
commit 15cd871
Showing
11 changed files
with
228 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
#pragma once | ||
// shared/sound_convert.h | ||
// common sound render conversions | ||
// NSFPlay internal 28-bit stereo to various outputs | ||
// inlined to facilitate compiler optimizations, especially witha constant number of samples | ||
|
||
#include <cstdint> | ||
|
||
inline void sound_convert_sint32s(const uint32_t samples, const int32_t* input, int32_t* output); | ||
inline void sound_convert_sint32m(const uint32_t samples, const int32_t* input, int32_t* output); | ||
inline void sound_convert_sint24s(const uint32_t samples, const int32_t* input, uint8_t* output); | ||
inline void sound_convert_sint24m(const uint32_t samples, const int32_t* input, uint8_t* output); | ||
inline void sound_convert_sint16s(const uint32_t samples, const int32_t* input, int16_t* output); | ||
inline void sound_convert_sint16m(const uint32_t samples, const int32_t* input, int16_t* output); | ||
inline void sound_convert_uint8s( const uint32_t samples, const int32_t* input, uint8_t* output); | ||
inline void sound_convert_uint8m( const uint32_t samples, const int32_t* input, uint8_t* output); | ||
|
||
// | ||
// Inline Implementation | ||
// | ||
|
||
inline int32_t sound_convert_clamp(const int32_t s) | ||
{ | ||
static const int32_t SCMAX = ((1<<27)-1); | ||
static const int32_t SCMIN = -((1<<27)-1); | ||
if (s > SCMAX) return SCMAX; | ||
else if (s < SCMIN) return SCMIN; | ||
return s; | ||
} | ||
|
||
// single sample clamp and convert | ||
|
||
inline int32_t sound_convert_clamp32(const int32_t s) | ||
{ | ||
return sound_convert_clamp(s) << 4; | ||
} | ||
|
||
inline int32_t sound_convert_clamp24(const int32_t s) | ||
{ | ||
return sound_convert_clamp(s) >> 4; | ||
} | ||
|
||
inline int16_t sound_convert_clamp16(const int32_t s) | ||
{ | ||
return int16_t(sound_convert_clamp(s) >> 12); | ||
} | ||
|
||
inline uint8_t sound_convert_clamp8(const int32_t s) | ||
{ | ||
return uint8_t((sound_convert_clamp(s) >> 20) + (1<<7)); | ||
} | ||
|
||
// stereo to mono single sample clamp and convert | ||
|
||
inline int32_t sound_convert_clamp32m(const int32_t s0, const int32_t s1) | ||
{ | ||
return sound_convert_clamp32((s0>>1)+(s1>>1)); // shifting first avoids reducing overhead | ||
} | ||
|
||
inline int32_t sound_convert_clamp24m(const int32_t s0, const int32_t s1) | ||
{ | ||
return sound_convert_clamp24((s0>>1)+(s1>>1)); | ||
} | ||
|
||
inline int16_t sound_convert_clamp16m(const int32_t s0, const int32_t s1) | ||
{ | ||
return sound_convert_clamp16((s0>>1)+(s1>>1)); | ||
} | ||
|
||
inline uint8_t sound_convert_clamp8m(const int32_t s0, const int32_t s1) | ||
{ | ||
return sound_convert_clamp8((s0>>1)+(s1>>1)); | ||
} | ||
|
||
// batch conversion | ||
|
||
inline void sound_convert_sint32s(const uint32_t samples, const int32_t* input, int32_t* output) | ||
{ | ||
for (uint32_t i=0; i<(samples*2); ++i) | ||
output[i] = sound_convert_clamp32(input[i]); | ||
} | ||
|
||
inline void sound_convert_sint32m(const uint32_t samples, const int32_t* input, int32_t* output) | ||
{ | ||
for (uint32_t i=0; i<samples; ++i) | ||
output[i] = sound_convert_clamp32m(input[(i*2)+0],input[(i*2)+1]); | ||
} | ||
|
||
inline void sound_convert_sint24s(const uint32_t samples, const int32_t* input, uint8_t* output) | ||
{ | ||
for (uint32_t i=0,j=0; i<(samples*3); i+=3,j+=1) | ||
{ | ||
const int32_t s = sound_convert_clamp24(input[j]); | ||
output[i+0] = uint8_t((s >> 0) & 0xFF); | ||
output[i+1] = uint8_t((s >> 8) & 0xFF); | ||
output[i+2] = uint8_t((s >> 16) & 0xFF); | ||
} | ||
} | ||
|
||
inline void sound_convert_sint24m(const uint32_t samples, const int32_t* input, uint8_t* output) | ||
{ | ||
for (uint32_t i=0,j=0; i<(samples*3); i+=3,j+=2) | ||
{ | ||
const int32_t s = sound_convert_clamp24m(input[j+0],input[j+1]); | ||
output[i+0] = uint8_t((s >> 0) & 0xFF); | ||
output[i+1] = uint8_t((s >> 8) & 0xFF); | ||
output[i+2] = uint8_t((s >> 16) & 0xFF); | ||
} | ||
} | ||
|
||
inline void sound_convert_sint16s(const uint32_t samples, const int32_t* input, int16_t* output) | ||
{ | ||
for (uint32_t i=0; i<(samples*2); ++i) | ||
output[i] = sound_convert_clamp16(input[i]); | ||
} | ||
|
||
inline void sound_convert_sint16m(const uint32_t samples, const int32_t* input, int16_t* output) | ||
{ | ||
for (uint32_t i=0; i<samples; ++i) | ||
output[i] = sound_convert_clamp16m(input[(i*2)+0],input[(i*2)+1]); | ||
} | ||
|
||
inline void sound_convert_uint8s(const uint32_t samples, const int32_t* input, uint8_t* output) | ||
{ | ||
for (uint32_t i=0; i<(samples*2); ++i) | ||
output[i] = sound_convert_clamp8(input[i]); | ||
} | ||
|
||
inline void sound_convert_uint8m(const uint32_t samples, const int32_t* input, uint8_t* output) | ||
{ | ||
for (uint32_t i=0; i<samples; ++i) | ||
output[i] = sound_convert_clamp8m(input[(i*2)+0],input[(i*2)+1]); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// wav_file.cpp | ||
// WAV file output | ||
|
||
#include "wav_file.h" | ||
//#include <cstdio> // FILE, std::fwrite, std::ftell, std::fseek | ||
|
||
static inline void headfc(uint8_t* head, int pos, const char* fc) { for (int i=0;i<4;++i) head[pos+i] = fc[i]; } | ||
static inline void head16( uint8_t* head, int pos, uint16_t v) { for (int i=0;i<2;++i) head[pos+i] = (v>>(8*i))&0xFF; } | ||
static inline void head32( uint8_t* head, int pos, uint32_t v) { for (int i=0;i<4;++i) head[pos+i] = (v>>(8*i))&0xFF; } | ||
|
||
bool wave_file_begin(FILE* f, uint32_t samplerate, uint16_t channels, uint16_t bits) | ||
{ | ||
uint8_t head[0x2C]; | ||
// RIFF master chunk | ||
headfc(head,0x00,"RIFF"); | ||
head32(head,0x04,0); // (file size - 12) | ||
headfc(head,0x08,"WAVE"); | ||
// fmt chunk | ||
headfc(head,0x0C,"fmt "); | ||
head32(head,0x10,16); // fmt chunk size | ||
head16(head,0x14,0x01); // PCM data | ||
head16(head,0x16,channels); | ||
head32(head,0x18,samplerate); | ||
head32(head,0x1C,samplerate * channels * (bits/8)); | ||
head16(head,0x20,channels * (bits/8)); | ||
head16(head,0x22,bits); | ||
// data chunk | ||
headfc(head,0x24,"data"); | ||
head32(head,0x28,0); // data chunk size | ||
return 0x2C == std::fwrite(head,1,0x2C,f); | ||
} | ||
|
||
bool wave_file_finish(FILE* f) | ||
{ | ||
uint8_t head[4]; | ||
bool result = true; | ||
long fsize = std::ftell(f); | ||
if (fsize & 1) { result &= (0 == std::fputc(0,f)); ++fsize; } // padding byte needed for odd data chunk size | ||
// RIFF chunk size | ||
result &= (0 == std::fseek(f,0x04,SEEK_SET)); | ||
head32(head,0,fsize-12); | ||
result &= (4 == std::fwrite(head,1,4,f)); | ||
// data chunk size | ||
result &= (0 == std::fseek(f,0x28,SEEK_SET)); | ||
head32(head,0,fsize-(0x2C)); | ||
result &= (4 == std::fwrite(head,1,4,f)); | ||
// return to end of file | ||
std::fseek(f,0,SEEK_END); | ||
return result; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#pragma once | ||
// shared/wav_file.h | ||
// WAV file output | ||
|
||
#include <cstdint> | ||
#include <cstdio> // FILE | ||
|
||
// 1. Open FILE. | ||
// 2. Write header: | ||
bool wave_file_begin(FILE* f, uint32_t samplerate, uint16_t channels, uint16_t bits); | ||
// 3. Write sample data to FILE. | ||
// 4. Finish FILE by updating header with data sizes: | ||
bool wave_file_finish(FILE* f); | ||
// 5. Close FILE. | ||
|
||
// This creates a minimal RIFF WAVE (.WAV) file with no extra data fields. | ||
// The total file size must be less than 2GB or the header field sizes will be incorrect. |