2
$\begingroup$

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(); } } 

enter image description here

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(); 
$\endgroup$
4
  • 1
    $\begingroup$ 16 bit WAV file format uses signed integer representation with DC being at 0, in other words no dc offset. May be that's the problem ? $\endgroup$ Commented Apr 2, 2016 at 12:59
  • $\begingroup$ I do not think so because there are parts of the file that show a correct sine with DC = 0 as you can see. $\endgroup$ Commented Apr 2, 2016 at 13:20
  • $\begingroup$ what's your final code that works? I update your code with the solution in your Edit section, but after imported to Audacity, it's not sinus at all. $\endgroup$ Commented Sep 10, 2018 at 11:50
  • $\begingroup$ That << 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$ Commented Dec 29, 2023 at 20:57

3 Answers 3

1
$\begingroup$

Create low-frequency triangular or square waveform. Start from constant value, written into the wave. Generate one in audacity and save. Compare. Do not generate sine or anithing more compled right away. Start building complexity from simple components. Be smart, use simplicity and evolutionary approach.

$\endgroup$
4
  • $\begingroup$ This is what I am doing. But I asked this question on DSP because I hoped some experts directly recognize what the problem is. Hence I expect some kind of code-wise answer. $\endgroup$ Commented Apr 2, 2016 at 18:10
  • $\begingroup$ @user2366975 You need to hire a programmer for the 'code-wise' solution. The questions to debug your code are bad for obvious reasons. They are not even welocmmed I have checked that at SO. I have checked that. $\endgroup$ Commented Apr 2, 2016 at 19:22
  • $\begingroup$ Well I hoped someone would be so interested to copy the code and run it. Usually at least someone takes the time to read and try to understand what I am doing and then gives advice. Else I would not bother asking a question, because your kind of answer would then be the answer to almost every question. But thanks any way :) $\endgroup$ Commented Apr 2, 2016 at 19:48
  • $\begingroup$ Saying your kind of answer would then be the answer to almost every question you basically downplay the quality of other questions. When do something wrong, you have not good justification. But giving outrageous excuses you just dig deeper. $\endgroup$ Commented Apr 2, 2016 at 19:59
0
$\begingroup$

I think we should not perform shift operation on a negtive number. if we like the performance of shift operation, we should apply it on an uint16_t then convert the result back to int16_t.

$\endgroup$
-1
$\begingroup$

I used an int16_t array for the 16-bit sine wave data. The natural byte order for int16_t worked correctly when saved to an SD card and listened to the .wav file.

. . . writeWavHeader(); int i; double frequency = 333.0; double t; int16_t value; int high; int low; int n; double amp = 32000; int16_t data[256]; n = 0; while( n < 30000){ i = 0; while( i < 256){ // Mono 16 PCM: SAMPLE1: (low order byte) (high order byte) SAMPLE2: (low order byte) (high order byte) value = (int16_t)(amp * sin(2.0 * 3.14159 * frequency * n / sampleRate)); data[i] = value; i++; n++; } writeDataToWavFile(data, i); } void writeDataToWavFile(int16_t data[], int size) { subChunk2Size += numChannels * bitsPerSample/8 * size; wavFile.seek(40); wavFile.write((byte*)&subChunk2Size,4); wavFile.seek(4); chunkSize = 36 + subChunk2Size; wavFile.write((byte*)&chunkSize,4); wavFile.seek(wavFile.size()); // The size() equals EOF. wavFile.write((uint16_t*)data, size * 2); } 
$\endgroup$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.