Esempio n. 1
0
void SaveAudioClip(AudioProvider const& provider, fs::path const& path, int start_time, int end_time) {
	const auto max_samples = provider.GetNumSamples();
	const auto start_sample = std::min(max_samples, ((int64_t)start_time * provider.GetSampleRate() + 999) / 1000);
	const auto end_sample = util::mid(start_sample, ((int64_t)end_time * provider.GetSampleRate() + 999) / 1000, max_samples);

	const size_t bytes_per_sample = provider.GetBytesPerSample() * provider.GetChannels();
	const size_t bufsize = (end_sample - start_sample) * bytes_per_sample;

	writer out{path};
	out.write("RIFF");
	out.write<int32_t>(bufsize + 36);

	out.write("WAVEfmt ");
	out.write<int32_t>(16); // Size of chunk
	out.write<int16_t>(1);  // compression format (PCM)
	out.write<int16_t>(provider.GetChannels());
	out.write<int32_t>(provider.GetSampleRate());
	out.write<int32_t>(provider.GetSampleRate() * provider.GetChannels() * provider.GetBytesPerSample());
	out.write<int16_t>(provider.GetChannels() * provider.GetBytesPerSample());
	out.write<int16_t>(provider.GetBytesPerSample() * 8);

	out.write("data");
	out.write<int32_t>(bufsize);

	// samples per read
	size_t spr = 65536 / bytes_per_sample;
	std::vector<char> buf;
	for (int64_t i = start_sample; i < end_sample; i += spr) {
		spr = std::min<size_t>(spr, end_sample - i);
		buf.resize(spr * bytes_per_sample);
		provider.GetAudio(&buf[0], i, spr);
		out.write(buf);
	}
}
//////////////////////
// PortAudio callback
int PortAudioPlayer::paCallback(void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, PaTimestamp outTime, void *userData) {
	// Get provider
	PortAudioPlayer *player = (PortAudioPlayer *) userData;
	AudioProvider *provider = player->GetProvider();
	int end = 0;

	// Calculate how much left
	__int64 lenAvailable = player->endPos - player->playPos;
	uint64_t avail = 0;
	if (lenAvailable > 0) {
		avail = lenAvailable;
		if (avail > framesPerBuffer) {
			lenAvailable = framesPerBuffer;
			avail = lenAvailable;
		}
	}
	else {
		lenAvailable = 0;
		avail = 0;
	}

	// Play something
	if (lenAvailable > 0) {
		provider->GetAudio(outputBuffer,player->playPos,lenAvailable);
	}

	// Pad end with blank
	if (avail < (uint64_t) framesPerBuffer) {
		//provider->softStop = true;
	}

	// Set volume
	short *output = (short*) outputBuffer;
	for (unsigned int i=0;i<avail;i++) output[i] = MID(-(1<<15),int(output[i] * player->GetVolume()),(1<<15)-1);

	// Fill rest with blank
	for (unsigned int i=avail;i<framesPerBuffer;i++) output[i]=0;

	// Set play position (and real one)
	player->playPos += framesPerBuffer;
	player->realPlayPos = (__int64)(Pa_StreamTime(player->stream) - player->paStart) + player->startPos;

	// Cap to start if lower
	return end;
}