diff --git a/Builds/VisualStudio2019/resources.aps b/Builds/VisualStudio2019/resources.aps index 89faecc..606a6a0 100644 Binary files a/Builds/VisualStudio2019/resources.aps and b/Builds/VisualStudio2019/resources.aps differ diff --git a/Builds/VisualStudio2019/resources.rc b/Builds/VisualStudio2019/resources.rc index 66d6f9f..2370040 100644 --- a/Builds/VisualStudio2019/resources.rc +++ b/Builds/VisualStudio2019/resources.rc @@ -14,8 +14,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // IDR_VERSION VERSIONINFO - FILEVERSION 2022,5,4,1 - PRODUCTVERSION 2022,5,4,1 + FILEVERSION 2022,6,6,1 + PRODUCTVERSION 2022,6,6,1 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -32,12 +32,12 @@ BEGIN BEGIN VALUE "CompanyName", "Igor Bochkariov" VALUE "FileDescription", "Multi Channel Audio Capture" - VALUE "FileVersion", "2022.5.4.1" + VALUE "FileVersion", "2022.6.6.1" VALUE "InternalName", "mcac.exe" VALUE "LegalCopyright", "Copyright (C) 2022" VALUE "OriginalFilename", "mcac.exe" VALUE "ProductName", "Multi Channel Audio Capture" - VALUE "ProductVersion", "2022.5.4.1" + VALUE "ProductVersion", "2022.6.6.1" END END BLOCK "VarFileInfo" diff --git a/Source/asio_api.cpp b/Source/asio_api.cpp index 3456045..dc770c6 100644 --- a/Source/asio_api.cpp +++ b/Source/asio_api.cpp @@ -147,11 +147,10 @@ void AsioDevice::open() { error = driver->createBuffers(buffer_infos, input_channels_number + output_channels_number, preferred_buffer_size, &callbacks[index]); refuse(error); - for (int i = 0; i < input_channels_number; i += 1) { - sample_type_buffers[i] = (float*)calloc(preferred_buffer_size, sizeof(float)); + for (int i = 0; i < MAX_INPUT_CHANNELS; i++) { + circlebuf_init(&input_buffers[i]); + input_buffer_pointers[i] = &input_buffers[i]; } - circlebuf_init(&input_buffer); - circlebuf_init(&interleaved_buffer); driver_buffers_allocated = true; initialize_latencies(); @@ -197,17 +196,7 @@ void AsioDevice::close() { if (driver_buffers_allocated) { driver->disposeBuffers(); - - for (int i = 0; i < input_channels_number; i += 1) { - if (sample_type_buffers[i]) { - free(sample_type_buffers[i]); - sample_type_buffers[i] = NULL; - } - } - - circlebuf_free(&input_buffer); - circlebuf_free(&interleaved_buffer); - + for (int i = 0; i < MAX_INPUT_CHANNELS; i++) circlebuf_free(&input_buffers[i]); driver_buffers_allocated = false; } @@ -291,7 +280,7 @@ DWORD WINAPI AsioDevice::CaptureThread(void* data) { int wait_result = WaitForMultipleObjects(2, signals, false, INFINITE); if (wait_result == WAIT_OBJECT_0) { EnterCriticalSection(&device->buffer_section); - if (writer) writer->write_packet(&device->input_buffer); + if (writer) writer->write_packet(device->input_buffer_pointers); LeaveCriticalSection(&device->buffer_section); } else if (wait_result == WAIT_OBJECT_0 + 1) { @@ -394,45 +383,20 @@ ASIOTime* AsioDevice::buffer_switch_time_info(int device_index, ASIOTime* timeIn UNREFERENCED_PARAMETER(processNow); } -static inline void* fill_interleaved_buffer(size_t channels, size_t samples, float** fdata, struct circlebuf* interleaved_buffer) { - circlebuf_upsize(interleaved_buffer, channels * samples * BYTES_PER_SAMPLE); - float* buffer = (float*)circlebuf_data(interleaved_buffer, 0); - extern float last_buffer_magnitude[MAX_INPUT_CHANNELS]; - - for (size_t c = 0; c < channels; c++) { - if (fdata[c]) { - float sum_of_squares = 0.0f; - for (size_t i = 0; i < samples; i++) { - float sample = buffer[i * channels + c] = fdata[c][i]; - sum_of_squares += sample * sample; - } - last_buffer_magnitude[c] = sqrtf(sum_of_squares / samples); - } - else { - for (size_t i = 0; i < samples; i++) { - buffer[i * channels + c] = 0.0f; - } - last_buffer_magnitude[c] = 0.0f; - } - } - for (size_t c = channels; c < MAX_INPUT_CHANNELS; c++) { - last_buffer_magnitude[c] = 0.0f; - } - - return buffer; -} - static ULONGLONG last_time = 0; void AsioDevice::push_received_buffers(int buffer_index) { int skipped = 0; + for (int channel = 0; channel < input_channels_number; channel += 1) { if (active_channels[channel]) { + size_t data_size = input_buffers[channel - skipped].size; + circlebuf_upsize(&input_buffers[channel - skipped], data_size + (size_t)preferred_buffer_size * BYTES_PER_SAMPLE); if (sample_type == ASIOSTInt32LSB) { - convertInt32ToFloat((const char*)buffer_infos[channel].buffers[buffer_index], sample_type_buffers[channel - skipped], preferred_buffer_size); + convertInt32ToFloat((const char*)buffer_infos[channel].buffers[buffer_index], (float*)circlebuf_data(&input_buffers[channel - skipped], data_size), preferred_buffer_size); } else { - memcpy(sample_type_buffers[channel - skipped], buffer_infos[channel].buffers[buffer_index], preferred_buffer_size * BYTES_PER_SAMPLE); + memcpy(circlebuf_data(&input_buffers[channel - skipped], data_size), buffer_infos[channel].buffers[buffer_index], (size_t)preferred_buffer_size * BYTES_PER_SAMPLE); } } else { @@ -440,12 +404,13 @@ void AsioDevice::push_received_buffers(int buffer_index) { } } - fill_interleaved_buffer(active_channels_count, preferred_buffer_size, sample_type_buffers, &interleaved_buffer); - circlebuf_push_back(&input_buffer, circlebuf_data(&interleaved_buffer, 0), active_channels_count * preferred_buffer_size * BYTES_PER_SAMPLE); - extern float last_buffer_magnitude[MAX_INPUT_CHANNELS]; extern float buffer_magnitude[MAX_INPUT_CHANNELS]; + for (int channel = 0; channel < active_channels_count; channel++) { + last_buffer_magnitude[channel] = ((float*)circlebuf_data(&input_buffers[channel], 0))[0]; + } + for (int channel = 0; channel < input_channels_number; channel += 1) { if (buffer_magnitude[channel] < last_buffer_magnitude[channel]) { buffer_magnitude[channel] = last_buffer_magnitude[channel]; diff --git a/Source/asio_api.h b/Source/asio_api.h index ac6a565..f0ad6a5 100644 --- a/Source/asio_api.h +++ b/Source/asio_api.h @@ -33,10 +33,8 @@ class AsioDevice { int output_samples_per_10ms = 0; - float* sample_type_buffers[MAX_INPUT_CHANNELS] = { 0 }; - - struct circlebuf input_buffer = { 0 }; - struct circlebuf interleaved_buffer = { 0 }; + circlebuf input_buffers[MAX_INPUT_CHANNELS] = { 0 }; + circlebuf *input_buffer_pointers[MAX_INPUT_CHANNELS] = { 0 }; WinHandle stop_signal, receive_signal; WinHandle capture_thread; diff --git a/Source/writer.cpp b/Source/writer.cpp index bf8df35..3ff2db9 100644 --- a/Source/writer.cpp +++ b/Source/writer.cpp @@ -12,14 +12,12 @@ Writer::Writer(class AsioDevice *_device) { core_audio_ready = load_core_audio(); - circlebuf_init(&encode_buffer); circlebuf_init(&output_buffer); } Writer::~Writer() { uninit(); - circlebuf_free(&encode_buffer); circlebuf_free(&output_buffer); DeleteCriticalSection(&file_section); @@ -53,8 +51,8 @@ void Writer::init(double _sample_rate) { in.mSampleRate = sample_rate; in.mChannelsPerFrame = channels; in.mFormatID = kAudioFormatLinearPCM; - in.mFormatFlags = kAudioFormatFlagIsPacked | kAudioFormatFlagIsFloat; - in.mBytesPerFrame = channels * BYTES_PER_SAMPLE; + in.mFormatFlags = kAudioFormatFlagIsPacked | kAudioFormatFlagIsFloat | kAudioFormatFlagIsNonInterleaved; + in.mBytesPerFrame = BYTES_PER_SAMPLE; in.mFramesPerPacket = 1; in.mBytesPerPacket = in.mFramesPerPacket * in.mBytesPerFrame; in.mBitsPerChannel = BYTES_PER_SAMPLE * 8; @@ -100,7 +98,7 @@ void Writer::init(double _sample_rate) { kAudioChannelLayoutTag_AAC_4_0, kAudioChannelLayoutTag_AAC_5_0, kAudioChannelLayoutTag_AAC_6_0, - kAudioChannelLayoutTag_AAC_7_0, //distortion + kAudioChannelLayoutTag_AAC_7_0, kAudioChannelLayoutTag_AAC_Octagonal, }; @@ -220,18 +218,20 @@ OSStatus Writer::input_data_provider(AudioConverterRef inAudioConverter, UInt32* UInt32 bytes_required = (*ioNumberDataPackets) * active_writer->bytes_per_input_packet; - if (active_writer->input_buffer->size < bytes_required) { + if (active_writer->input_buffers[0]->size < bytes_required) { *ioNumberDataPackets = 0; return MORE_DATA_REQUIRED; } - circlebuf_upsize(&active_writer->encode_buffer, bytes_required); - - ioData->mBuffers[0].mNumberChannels = active_writer->channels; - ioData->mBuffers[0].mDataByteSize = bytes_required; - ioData->mBuffers[0].mData = circlebuf_data(&active_writer->encode_buffer, 0); - - circlebuf_pop_front(active_writer->input_buffer, ioData->mBuffers[0].mData, bytes_required); + for (int channel = 0; channel < active_writer->channels; channel++) { + ioData->mBuffers[channel].mNumberChannels = 1; + ioData->mBuffers[channel].mDataByteSize = bytes_required; + if (active_writer->input_buffers[channel]->size < bytes_required) { + circlebuf_push_back_zero(active_writer->input_buffers[channel], bytes_required); + } + ioData->mBuffers[channel].mData = circlebuf_data(active_writer->input_buffers[channel], 0); + circlebuf_pop_front(active_writer->input_buffers[channel], ioData->mBuffers[channel].mData, bytes_required); + } return 0; @@ -239,7 +239,7 @@ OSStatus Writer::input_data_provider(AudioConverterRef inAudioConverter, UInt32* UNUSED_PARAMETER(outDataPacketDescription); } -void Writer::write_packet(circlebuf* _input_buffer) { +void Writer::write_packet(circlebuf **_input_buffers) { if (!core_audio_ready) { message = "MCAC: AAC library not available"; PostMessage(message_window, WM_USER_WRITER_ERROR, 0, 0); @@ -247,11 +247,13 @@ void Writer::write_packet(circlebuf* _input_buffer) { } if (stop) { - circlebuf_pop_front(_input_buffer, nullptr, _input_buffer->size); + for (int i = 0; i < MAX_INPUT_CHANNELS; i++) { + circlebuf_pop_front(_input_buffers[i], nullptr, _input_buffers[i]->size); + } return; } - input_buffer = _input_buffer; + input_buffers = _input_buffers; UInt32 packets_count = 1; AudioBufferList output_buffers = { 0 }; diff --git a/Source/writer.h b/Source/writer.h index 9f78d75..0bc18c0 100644 --- a/Source/writer.h +++ b/Source/writer.h @@ -40,9 +40,8 @@ class Writer { AudioConverterRef converter = nullptr; unsigned bytes_per_input_packet = 0; unsigned sample_rate = 0; - struct circlebuf encode_buffer = { 0 }; struct circlebuf output_buffer = { 0 }; - circlebuf* input_buffer = nullptr; + circlebuf** input_buffers = nullptr; FILE* file = nullptr; bool stop = true; CRITICAL_SECTION file_section; @@ -63,5 +62,5 @@ class Writer { bool open(); void close(bool report = true); static OSStatus input_data_provider(AudioConverterRef inAudioConverter, UInt32* ioNumberDataPackets, AudioBufferList* ioData, AudioStreamPacketDescription** outDataPacketDescription, void* inUserData); - void write_packet(circlebuf* _input_buffer); + void write_packet(circlebuf **_input_buffers); };