This seems a simple task, yet I am making some stupid mistakes I am not able to find. I create a sinus wave (integer) and then convert it to 16 bit char, little endian. Then I save to file and open it in Audacity (see image below). The first channel in the image is created by Audacity, the second by me. Something is really wrong there. I think it must be in the bit shifting, because if I use 8 Bit, it works. So the extra byte causes trouble but I don't see, how.
#include <bitset> #include <iostream> #include <chrono> #include <math.h> #include <fstream> #include <iomanip> #define PI 3.14159265359 void test_sine16Bit(){ int samplesize = 16; unsigned int samplerate = 44100; int duration = 3; // seconds int channels = 1; //long samples = 4096; long samples = samplerate * duration; // per channel long total_samples = samples * channels; // all channels // Create test input buffer char input[total_samples * samplesize/8]; // Initialize test buffer with zeros for (int i=0;i<total_samples * samplesize/8;++i){ input[i]=0; } // Create test input int total_index=0; char graph[20]; for (long i=0;i<samples;++i){ // Channel 1: 440 Hz sinus int sinus = .8*0x8000*sin(2*PI*440*i/samplerate); // amplitude = 0.8 * max range; max range = 0x8000 = 32768 ( max value for 16 Bit signed int ) // Little Endian: BUG HERE? input[total_index] = sinus & 0xFF; // LoByte //input[total_index+1] = (sinus & 0xFF00) >> 8; // HiByte input[total_index+1] = (sinus >> 8) & 0xFF; // HiByte total_index += 2; } // Export raw audio data to file std::ofstream fout("sine_char16bit.raw"); if (fout.is_open()){ long idx = 0; for(long i = 0; i < samples; ++i){ fout << input[idx] << input[idx+1]; idx+=2; } fout.close(); } } EDIT:
Found the solution: You need to open the file in binary mode and not write via <<, but with put or write.
std::ofstream fout("sine_char16bit.raw", std::ios::out | std::ios::binary); if (fout.is_open()){ fout.write(input, total_samples * samplesize/8); } fout.close(); 
Editsection, but after imported to Audacity, it's not sinus at all. $\endgroup$<<operator for I/O in C++ is sooooooooooo stupid and confusing. (Since it already exists for Arithmetic Shift Left.) C++ could have been a really cool and compact OOP language. Instead, they tried to make it be all things to all men and the bloated result is like Ada. $\endgroup$