| ¶Ô±ÈÐÂÎļþ |
| | |
| | | { |
| | | "Version": 1, |
| | | "WorkspaceRootPath": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\ReverbHallRoom\\", |
| | | "Documents": [ |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{1400541B-B713-435F-95FB-9F7F15065495}|ReverbHallRoom.vcxproj|E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\ReverbHallRoom\\ReverbHallRoom.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", |
| | | "RelativeMoniker": "D:0:0:{1400541B-B713-435F-95FB-9F7F15065495}|ReverbHallRoom.vcxproj|solutionrelative:ReverbHallRoom.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{1400541B-B713-435F-95FB-9F7F15065495}|ReverbHallRoom.vcxproj|E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{1400541B-B713-435F-95FB-9F7F15065495}|ReverbHallRoom.vcxproj|E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_wrapper.c||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{1400541B-B713-435F-95FB-9F7F15065495}|ReverbHallRoom.vcxproj|E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_wrapper.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{1400541B-B713-435F-95FB-9F7F15065495}|ReverbHallRoom.vcxproj|E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{1400541B-B713-435F-95FB-9F7F15065495}|ReverbHallRoom.vcxproj|E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_utils\\Programs.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{1400541B-B713-435F-95FB-9F7F15065495}|ReverbHallRoom.vcxproj|E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_utils\\RandomBuffer.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{1400541B-B713-435F-95FB-9F7F15065495}|ReverbHallRoom.vcxproj|E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_utils\\RandomBuffer.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" |
| | | } |
| | | ], |
| | | "DocumentGroupContainers": [ |
| | | { |
| | | "Orientation": 0, |
| | | "VerticalTabListWidth": 256, |
| | | "DocumentGroups": [ |
| | | { |
| | | "DockedWidth": 220, |
| | | "SelectedChildIndex": 9, |
| | | "Children": [ |
| | | { |
| | | "$type": "Bookmark", |
| | | "Name": "ST:0:0:{a0c5197d-0ac7-4b63-97cd-8872a789d233}" |
| | | }, |
| | | { |
| | | "$type": "Bookmark", |
| | | "Name": "ST:128:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}" |
| | | }, |
| | | { |
| | | "$type": "Bookmark", |
| | | "Name": "ST:129:0:{1fc202d4-d401-403c-9834-5b218574bb67}" |
| | | }, |
| | | { |
| | | "$type": "Bookmark", |
| | | "Name": "ST:0:0:{53d10d51-d2d8-3452-ab88-12f687ed0782}" |
| | | }, |
| | | { |
| | | "$type": "Bookmark", |
| | | "Name": "ST:0:0:{3ae79031-e1bc-11d0-8f78-00a0c9110057}" |
| | | }, |
| | | { |
| | | "$type": "Bookmark", |
| | | "Name": "ST:0:0:{40ea2e6b-2121-4bb8-a43e-c83c04b51041}" |
| | | }, |
| | | { |
| | | "$type": "Bookmark", |
| | | "Name": "ST:0:0:{aa2115a1-9712-457b-9047-dbb71ca2cdd2}" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 6, |
| | | "Title": "RandomBuffer.cpp", |
| | | "DocumentMoniker": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_utils\\RandomBuffer.cpp", |
| | | "RelativeDocumentMoniker": "..\\reverb_utils\\RandomBuffer.cpp", |
| | | "ToolTip": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_utils\\RandomBuffer.cpp", |
| | | "RelativeToolTip": "..\\reverb_utils\\RandomBuffer.cpp", |
| | | "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", |
| | | "WhenOpened": "2026-03-10T09:35:50.55Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 7, |
| | | "Title": "RandomBuffer.h", |
| | | "DocumentMoniker": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_utils\\RandomBuffer.h", |
| | | "RelativeDocumentMoniker": "..\\reverb_utils\\RandomBuffer.h", |
| | | "ToolTip": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_utils\\RandomBuffer.h", |
| | | "RelativeToolTip": "..\\reverb_utils\\RandomBuffer.h", |
| | | "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000680|", |
| | | "WhenOpened": "2026-03-10T09:35:49.431Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 0, |
| | | "Title": "ReverbHallRoom.cpp", |
| | | "DocumentMoniker": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\ReverbHallRoom\\ReverbHallRoom.cpp", |
| | | "RelativeDocumentMoniker": "ReverbHallRoom.cpp", |
| | | "ToolTip": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\ReverbHallRoom\\ReverbHallRoom.cpp", |
| | | "RelativeToolTip": "ReverbHallRoom.cpp", |
| | | "ViewState": "AgIAAB4AAAAAAAAAAAAAACgAAAAyAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", |
| | | "WhenOpened": "2026-03-10T09:03:46.843Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 3, |
| | | "Title": "reverb_wrapper.h", |
| | | "DocumentMoniker": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_wrapper.h", |
| | | "RelativeDocumentMoniker": "..\\reverb_wrapper.h", |
| | | "ToolTip": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_wrapper.h", |
| | | "RelativeToolTip": "..\\reverb_wrapper.h", |
| | | "ViewState": "AgIAAAwAAAAAAAAAAAAAACsAAAAAAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000680|", |
| | | "WhenOpened": "2026-03-10T09:37:03.415Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 5, |
| | | "Title": "Programs.h", |
| | | "DocumentMoniker": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_utils\\Programs.h", |
| | | "RelativeDocumentMoniker": "..\\reverb_utils\\Programs.h", |
| | | "ToolTip": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_utils\\Programs.h", |
| | | "RelativeToolTip": "..\\reverb_utils\\Programs.h", |
| | | "ViewState": "AgIAAAAAAAAAAAAAAAAAAAEAAAAMAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000680|", |
| | | "WhenOpened": "2026-03-10T09:14:17.518Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 1, |
| | | "Title": "reverb.cpp", |
| | | "DocumentMoniker": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb.cpp", |
| | | "RelativeDocumentMoniker": "..\\reverb.cpp", |
| | | "ToolTip": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb.cpp", |
| | | "RelativeToolTip": "..\\reverb.cpp", |
| | | "ViewState": "AgIAAEQAAAAAAAAAAAAQwEoAAAAqAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", |
| | | "WhenOpened": "2026-03-10T09:06:15.139Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 2, |
| | | "Title": "reverb_wrapper.c", |
| | | "DocumentMoniker": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_wrapper.c", |
| | | "RelativeDocumentMoniker": "..\\reverb_wrapper.c", |
| | | "ToolTip": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_wrapper.c", |
| | | "RelativeToolTip": "..\\reverb_wrapper.c", |
| | | "ViewState": "AgIAABUAAAAAAAAAAAAAADQAAAAAAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000423|", |
| | | "WhenOpened": "2026-03-10T09:36:48.616Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 4, |
| | | "Title": "reverb.h", |
| | | "DocumentMoniker": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb.h", |
| | | "RelativeDocumentMoniker": "..\\reverb.h", |
| | | "ToolTip": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb.h", |
| | | "RelativeToolTip": "..\\reverb.h", |
| | | "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000680|", |
| | | "WhenOpened": "2026-03-10T09:38:04.142Z", |
| | | "EditorCaption": "" |
| | | } |
| | | ] |
| | | }, |
| | | { |
| | | "DockedWidth": 58, |
| | | "SelectedChildIndex": -1, |
| | | "Children": [ |
| | | { |
| | | "$type": "Bookmark", |
| | | "Name": "ST:283709:0:{1a46fd64-28d5-0019-8eb3-17a02d419b53}" |
| | | } |
| | | ] |
| | | } |
| | | ] |
| | | } |
| | | ] |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | { |
| | | "Version": 1, |
| | | "WorkspaceRootPath": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\ReverbHallRoom\\", |
| | | "Documents": [ |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{1400541B-B713-435F-95FB-9F7F15065495}|ReverbHallRoom.vcxproj|E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\ReverbHallRoom\\ReverbHallRoom.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}", |
| | | "RelativeMoniker": "D:0:0:{1400541B-B713-435F-95FB-9F7F15065495}|ReverbHallRoom.vcxproj|solutionrelative:ReverbHallRoom.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{1400541B-B713-435F-95FB-9F7F15065495}|ReverbHallRoom.vcxproj|E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{1400541B-B713-435F-95FB-9F7F15065495}|ReverbHallRoom.vcxproj|E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_wrapper.c||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{1400541B-B713-435F-95FB-9F7F15065495}|ReverbHallRoom.vcxproj|E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_wrapper.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{1400541B-B713-435F-95FB-9F7F15065495}|ReverbHallRoom.vcxproj|E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{1400541B-B713-435F-95FB-9F7F15065495}|ReverbHallRoom.vcxproj|E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_utils\\Programs.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{1400541B-B713-435F-95FB-9F7F15065495}|ReverbHallRoom.vcxproj|E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_utils\\RandomBuffer.cpp||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" |
| | | }, |
| | | { |
| | | "AbsoluteMoniker": "D:0:0:{1400541B-B713-435F-95FB-9F7F15065495}|ReverbHallRoom.vcxproj|E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_utils\\RandomBuffer.h||{D0E1A5C6-B359-4E41-9B60-3365922C2A22}" |
| | | } |
| | | ], |
| | | "DocumentGroupContainers": [ |
| | | { |
| | | "Orientation": 0, |
| | | "VerticalTabListWidth": 256, |
| | | "DocumentGroups": [ |
| | | { |
| | | "DockedWidth": 220, |
| | | "SelectedChildIndex": 9, |
| | | "Children": [ |
| | | { |
| | | "$type": "Bookmark", |
| | | "Name": "ST:0:0:{a0c5197d-0ac7-4b63-97cd-8872a789d233}" |
| | | }, |
| | | { |
| | | "$type": "Bookmark", |
| | | "Name": "ST:128:0:{116d2292-e37d-41cd-a077-ebacac4c8cc4}" |
| | | }, |
| | | { |
| | | "$type": "Bookmark", |
| | | "Name": "ST:129:0:{1fc202d4-d401-403c-9834-5b218574bb67}" |
| | | }, |
| | | { |
| | | "$type": "Bookmark", |
| | | "Name": "ST:0:0:{53d10d51-d2d8-3452-ab88-12f687ed0782}" |
| | | }, |
| | | { |
| | | "$type": "Bookmark", |
| | | "Name": "ST:0:0:{3ae79031-e1bc-11d0-8f78-00a0c9110057}" |
| | | }, |
| | | { |
| | | "$type": "Bookmark", |
| | | "Name": "ST:0:0:{40ea2e6b-2121-4bb8-a43e-c83c04b51041}" |
| | | }, |
| | | { |
| | | "$type": "Bookmark", |
| | | "Name": "ST:0:0:{aa2115a1-9712-457b-9047-dbb71ca2cdd2}" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 6, |
| | | "Title": "RandomBuffer.cpp", |
| | | "DocumentMoniker": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_utils\\RandomBuffer.cpp", |
| | | "RelativeDocumentMoniker": "..\\reverb_utils\\RandomBuffer.cpp", |
| | | "ToolTip": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_utils\\RandomBuffer.cpp", |
| | | "RelativeToolTip": "..\\reverb_utils\\RandomBuffer.cpp", |
| | | "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", |
| | | "WhenOpened": "2026-03-10T09:35:50.55Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 7, |
| | | "Title": "RandomBuffer.h", |
| | | "DocumentMoniker": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_utils\\RandomBuffer.h", |
| | | "RelativeDocumentMoniker": "..\\reverb_utils\\RandomBuffer.h", |
| | | "ToolTip": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_utils\\RandomBuffer.h", |
| | | "RelativeToolTip": "..\\reverb_utils\\RandomBuffer.h", |
| | | "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000680|", |
| | | "WhenOpened": "2026-03-10T09:35:49.431Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 0, |
| | | "Title": "ReverbHallRoom.cpp", |
| | | "DocumentMoniker": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\ReverbHallRoom\\ReverbHallRoom.cpp", |
| | | "RelativeDocumentMoniker": "ReverbHallRoom.cpp", |
| | | "ToolTip": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\ReverbHallRoom\\ReverbHallRoom.cpp", |
| | | "RelativeToolTip": "ReverbHallRoom.cpp", |
| | | "ViewState": "AgIAAB4AAAAAAAAAAAAAACgAAAAyAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", |
| | | "WhenOpened": "2026-03-10T09:03:46.843Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 3, |
| | | "Title": "reverb_wrapper.h", |
| | | "DocumentMoniker": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_wrapper.h", |
| | | "RelativeDocumentMoniker": "..\\reverb_wrapper.h", |
| | | "ToolTip": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_wrapper.h", |
| | | "RelativeToolTip": "..\\reverb_wrapper.h", |
| | | "ViewState": "AgIAAAwAAAAAAAAAAAAAACsAAAAAAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000680|", |
| | | "WhenOpened": "2026-03-10T09:37:03.415Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 5, |
| | | "Title": "Programs.h", |
| | | "DocumentMoniker": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_utils\\Programs.h", |
| | | "RelativeDocumentMoniker": "..\\reverb_utils\\Programs.h", |
| | | "ToolTip": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_utils\\Programs.h", |
| | | "RelativeToolTip": "..\\reverb_utils\\Programs.h", |
| | | "ViewState": "AgIAAAAAAAAAAAAAAAAAAAEAAAAMAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000680|", |
| | | "WhenOpened": "2026-03-10T09:14:17.518Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 1, |
| | | "Title": "reverb.cpp", |
| | | "DocumentMoniker": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb.cpp", |
| | | "RelativeDocumentMoniker": "..\\reverb.cpp", |
| | | "ToolTip": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb.cpp", |
| | | "RelativeToolTip": "..\\reverb.cpp", |
| | | "ViewState": "AgIAAEQAAAAAAAAAAAAQwEoAAAAqAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000677|", |
| | | "WhenOpened": "2026-03-10T09:06:15.139Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 2, |
| | | "Title": "reverb_wrapper.c", |
| | | "DocumentMoniker": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_wrapper.c", |
| | | "RelativeDocumentMoniker": "..\\reverb_wrapper.c", |
| | | "ToolTip": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb_wrapper.c", |
| | | "RelativeToolTip": "..\\reverb_wrapper.c", |
| | | "ViewState": "AgIAABUAAAAAAAAAAAAAADQAAAAAAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000423|", |
| | | "WhenOpened": "2026-03-10T09:36:48.616Z", |
| | | "EditorCaption": "" |
| | | }, |
| | | { |
| | | "$type": "Document", |
| | | "DocumentIndex": 4, |
| | | "Title": "reverb.h", |
| | | "DocumentMoniker": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb.h", |
| | | "RelativeDocumentMoniker": "..\\reverb.h", |
| | | "ToolTip": "E:\\ADI_Prj\\z_git_fold_temp\\03-audio_process\\cbb_RoomReverb\\reverb.h", |
| | | "RelativeToolTip": "..\\reverb.h", |
| | | "ViewState": "AgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", |
| | | "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.000680|", |
| | | "WhenOpened": "2026-03-10T09:38:04.142Z", |
| | | "EditorCaption": "" |
| | | } |
| | | ] |
| | | }, |
| | | { |
| | | "DockedWidth": 58, |
| | | "SelectedChildIndex": -1, |
| | | "Children": [ |
| | | { |
| | | "$type": "Bookmark", |
| | | "Name": "ST:283709:0:{1a46fd64-28d5-0019-8eb3-17a02d419b53}" |
| | | } |
| | | ] |
| | | } |
| | | ] |
| | | } |
| | | ] |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | |  |
| | | #include <iostream> |
| | | #include <vector> |
| | | #include "reverb.h" |
| | | #include "reverb_wrapper.h" |
| | | #include "dr_wav.h" |
| | | |
| | | |
| | | int main() |
| | | { |
| | | unsigned int channels = 1, frame_size = 64, sample_rate = 48e3; double dry = 0, early = 0, late = 0.8; int input_mix_on = 0, hight_cut_on = 0; // 1~6 |
| | | int low_cut_on = 0; double input_mix = 0, high_cut_freq = 0, low_cut_freq = 0, cross_seed = 0; int taps_on = 1; double taps_count = 0.5; // 7~12 |
| | | double taps_pre_delay = 0.2, taps_decay = 0.5, taps_length = 0.1; int early_difus_on = 1; double early_difus_count = 0.5, early_difus_delay = 0.3; // 7~19 |
| | | double early_difus_feedback = 0.3, early_difus_mod_amt = 0.2, early_difus_mod_rate = 0.1; int late_mode = 1, late_reflect_on = 1; double late_line_count = 0.3; // 20~25 |
| | | double late_line_size = 0.4, late_line_mod_amt = 0.2, late_line_decay = 0.3, late_line_mod_rate = 0.1, late_difus_count = 0.1, late_difus_delay = 0.2; // 26~31 |
| | | double late_difus_feedback = 0.3, late_difus_mod_amt = 0.3, late_difus_mod_rate = 0.4; int eq_low_shelf_on = 0, eq_high_shelf_on = 0, eq_low_pass_on = 0; // 32~37 |
| | | double eq_low_shelf_freq = 0.1, eq_low_shelf_gain = 0.1, eq_high_shelf_freq = 0.1, eq_high_shelf_gain = 0.1, eq_low_pass_freq = 0.2; // 38~42 |
| | | |
| | | Reverb *reverb[1]; |
| | | reverb_wrapper_init((void **)reverb, channels, frame_size, sample_rate, dry, early, late, input_mix_on, hight_cut_on, |
| | | low_cut_on, input_mix, high_cut_freq, low_cut_freq, cross_seed, taps_on, taps_count, taps_pre_delay, taps_decay, taps_length, early_difus_on, early_difus_count, early_difus_delay, |
| | | early_difus_feedback, early_difus_mod_amt, early_difus_mod_rate, late_mode, late_reflect_on, late_line_count, late_line_size, late_line_mod_amt, late_line_decay = 0.1, late_line_mod_rate, late_difus_count, late_difus_delay, // 20~31 |
| | | late_difus_feedback, late_difus_mod_amt, late_difus_mod_rate, eq_low_shelf_on, eq_high_shelf_on, eq_low_pass_on, eq_low_shelf_freq, eq_low_shelf_gain, eq_high_shelf_freq = 0.1, eq_high_shelf_gain, eq_low_pass_freq // 32~42 |
| | | ); |
| | | |
| | | |
| | | // 读å
¥wavè¯é³æä»¶ |
| | | drwav_uint64 samples; |
| | | float* pSampleDataIn = drwav_open_file_and_read_pcm_frames_f32("E:\\music\\Voice_print\\mengwanzhou.wav", &channels, &sample_rate, &samples, NULL); |
| | | if (pSampleDataIn == NULL) { |
| | | return -1; |
| | | } |
| | | |
| | | int frame_count = samples / frame_size; |
| | | samples = frame_count * frame_size; |
| | | std::vector<float> outputData(samples); |
| | | |
| | | for (int i = 0; i < frame_count; i++) { |
| | | float *src = pSampleDataIn + i * frame_size; |
| | | float *dst = outputData.data() + i * frame_size; |
| | | reverb_wrapper_process(*reverb, src, dst); |
| | | } |
| | | |
| | | // å°å¤çåé³é¢æ°æ®åå
¥wavæä»¶ |
| | | drwav_data_format format; |
| | | format.container = drwav_container_riff; |
| | | format.format = DR_WAVE_FORMAT_IEEE_FLOAT; |
| | | format.channels = channels; |
| | | format.sampleRate = sample_rate; |
| | | format.bitsPerSample = 32; |
| | | |
| | | drwav wav; |
| | | if (!drwav_init_file_write(&wav, "output.wav", &format, NULL)) { |
| | | std::cerr << "Error: Cannot create output file" << std::endl; |
| | | return -1; |
| | | } |
| | | |
| | | drwav_uint64 framesWritten = drwav_write_pcm_frames(&wav, samples, outputData.data()); |
| | | if (framesWritten != samples) { |
| | | std::cerr << "Error: Did not write all frames." << std::endl; |
| | | } |
| | | |
| | | drwav_uninit(&wav); |
| | | drwav_free(pSampleDataIn, NULL); |
| | | |
| | | std::cout << "Done." << std::endl; |
| | | |
| | | return 0; |
| | | } |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | |  |
| | | Microsoft Visual Studio Solution File, Format Version 12.00 |
| | | # Visual Studio Version 17 |
| | | VisualStudioVersion = 17.13.35828.75 d17.13 |
| | | MinimumVisualStudioVersion = 10.0.40219.1 |
| | | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReverbHallRoom", "ReverbHallRoom.vcxproj", "{1400541B-B713-435F-95FB-9F7F15065495}" |
| | | EndProject |
| | | Global |
| | | GlobalSection(SolutionConfigurationPlatforms) = preSolution |
| | | Debug|x64 = Debug|x64 |
| | | Debug|x86 = Debug|x86 |
| | | Release|x64 = Release|x64 |
| | | Release|x86 = Release|x86 |
| | | EndGlobalSection |
| | | GlobalSection(ProjectConfigurationPlatforms) = postSolution |
| | | {1400541B-B713-435F-95FB-9F7F15065495}.Debug|x64.ActiveCfg = Debug|x64 |
| | | {1400541B-B713-435F-95FB-9F7F15065495}.Debug|x64.Build.0 = Debug|x64 |
| | | {1400541B-B713-435F-95FB-9F7F15065495}.Debug|x86.ActiveCfg = Debug|Win32 |
| | | {1400541B-B713-435F-95FB-9F7F15065495}.Debug|x86.Build.0 = Debug|Win32 |
| | | {1400541B-B713-435F-95FB-9F7F15065495}.Release|x64.ActiveCfg = Release|x64 |
| | | {1400541B-B713-435F-95FB-9F7F15065495}.Release|x64.Build.0 = Release|x64 |
| | | {1400541B-B713-435F-95FB-9F7F15065495}.Release|x86.ActiveCfg = Release|Win32 |
| | | {1400541B-B713-435F-95FB-9F7F15065495}.Release|x86.Build.0 = Release|Win32 |
| | | EndGlobalSection |
| | | GlobalSection(SolutionProperties) = preSolution |
| | | HideSolutionNode = FALSE |
| | | EndGlobalSection |
| | | GlobalSection(ExtensibilityGlobals) = postSolution |
| | | SolutionGuid = {B1A4C62B-D68D-453D-9503-5D45576018FC} |
| | | EndGlobalSection |
| | | EndGlobal |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
| | | <ItemGroup Label="ProjectConfigurations"> |
| | | <ProjectConfiguration Include="Debug|Win32"> |
| | | <Configuration>Debug</Configuration> |
| | | <Platform>Win32</Platform> |
| | | </ProjectConfiguration> |
| | | <ProjectConfiguration Include="Release|Win32"> |
| | | <Configuration>Release</Configuration> |
| | | <Platform>Win32</Platform> |
| | | </ProjectConfiguration> |
| | | <ProjectConfiguration Include="Debug|x64"> |
| | | <Configuration>Debug</Configuration> |
| | | <Platform>x64</Platform> |
| | | </ProjectConfiguration> |
| | | <ProjectConfiguration Include="Release|x64"> |
| | | <Configuration>Release</Configuration> |
| | | <Platform>x64</Platform> |
| | | </ProjectConfiguration> |
| | | </ItemGroup> |
| | | <PropertyGroup Label="Globals"> |
| | | <VCProjectVersion>17.0</VCProjectVersion> |
| | | <Keyword>Win32Proj</Keyword> |
| | | <ProjectGuid>{1400541b-b713-435f-95fb-9f7f15065495}</ProjectGuid> |
| | | <RootNamespace>ReverbHallRoom</RootNamespace> |
| | | <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> |
| | | </PropertyGroup> |
| | | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> |
| | | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> |
| | | <ConfigurationType>Application</ConfigurationType> |
| | | <UseDebugLibraries>true</UseDebugLibraries> |
| | | <PlatformToolset>v143</PlatformToolset> |
| | | <CharacterSet>Unicode</CharacterSet> |
| | | </PropertyGroup> |
| | | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> |
| | | <ConfigurationType>Application</ConfigurationType> |
| | | <UseDebugLibraries>false</UseDebugLibraries> |
| | | <PlatformToolset>v143</PlatformToolset> |
| | | <WholeProgramOptimization>true</WholeProgramOptimization> |
| | | <CharacterSet>Unicode</CharacterSet> |
| | | </PropertyGroup> |
| | | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> |
| | | <ConfigurationType>Application</ConfigurationType> |
| | | <UseDebugLibraries>true</UseDebugLibraries> |
| | | <PlatformToolset>v143</PlatformToolset> |
| | | <CharacterSet>Unicode</CharacterSet> |
| | | </PropertyGroup> |
| | | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> |
| | | <ConfigurationType>Application</ConfigurationType> |
| | | <UseDebugLibraries>false</UseDebugLibraries> |
| | | <PlatformToolset>v143</PlatformToolset> |
| | | <WholeProgramOptimization>true</WholeProgramOptimization> |
| | | <CharacterSet>Unicode</CharacterSet> |
| | | </PropertyGroup> |
| | | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> |
| | | <ImportGroup Label="ExtensionSettings"> |
| | | </ImportGroup> |
| | | <ImportGroup Label="Shared"> |
| | | </ImportGroup> |
| | | <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> |
| | | <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> |
| | | </ImportGroup> |
| | | <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> |
| | | <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> |
| | | </ImportGroup> |
| | | <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> |
| | | <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> |
| | | </ImportGroup> |
| | | <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> |
| | | <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> |
| | | </ImportGroup> |
| | | <PropertyGroup Label="UserMacros" /> |
| | | <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> |
| | | <ClCompile> |
| | | <WarningLevel>Level3</WarningLevel> |
| | | <SDLCheck>true</SDLCheck> |
| | | <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
| | | <ConformanceMode>true</ConformanceMode> |
| | | </ClCompile> |
| | | <Link> |
| | | <SubSystem>Console</SubSystem> |
| | | <GenerateDebugInformation>true</GenerateDebugInformation> |
| | | </Link> |
| | | </ItemDefinitionGroup> |
| | | <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> |
| | | <ClCompile> |
| | | <WarningLevel>Level3</WarningLevel> |
| | | <FunctionLevelLinking>true</FunctionLevelLinking> |
| | | <IntrinsicFunctions>true</IntrinsicFunctions> |
| | | <SDLCheck>true</SDLCheck> |
| | | <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
| | | <ConformanceMode>true</ConformanceMode> |
| | | </ClCompile> |
| | | <Link> |
| | | <SubSystem>Console</SubSystem> |
| | | <EnableCOMDATFolding>true</EnableCOMDATFolding> |
| | | <OptimizeReferences>true</OptimizeReferences> |
| | | <GenerateDebugInformation>true</GenerateDebugInformation> |
| | | </Link> |
| | | </ItemDefinitionGroup> |
| | | <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> |
| | | <ClCompile> |
| | | <WarningLevel>Level3</WarningLevel> |
| | | <SDLCheck>true</SDLCheck> |
| | | <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions> |
| | | <ConformanceMode>true</ConformanceMode> |
| | | <AdditionalIncludeDirectories>E:\ADI_Prj\z_git_fold_temp\03-audio_process\cbb_RoomReverb;E:\ADI_Prj\z_git_fold_temp\03-audio_process\cbb_RoomReverb\reverb_utils;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> |
| | | </ClCompile> |
| | | <Link> |
| | | <SubSystem>Console</SubSystem> |
| | | <GenerateDebugInformation>true</GenerateDebugInformation> |
| | | </Link> |
| | | </ItemDefinitionGroup> |
| | | <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> |
| | | <ClCompile> |
| | | <WarningLevel>Level3</WarningLevel> |
| | | <FunctionLevelLinking>true</FunctionLevelLinking> |
| | | <IntrinsicFunctions>true</IntrinsicFunctions> |
| | | <SDLCheck>true</SDLCheck> |
| | | <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
| | | <ConformanceMode>true</ConformanceMode> |
| | | </ClCompile> |
| | | <Link> |
| | | <SubSystem>Console</SubSystem> |
| | | <EnableCOMDATFolding>true</EnableCOMDATFolding> |
| | | <OptimizeReferences>true</OptimizeReferences> |
| | | <GenerateDebugInformation>true</GenerateDebugInformation> |
| | | </Link> |
| | | </ItemDefinitionGroup> |
| | | <ItemGroup> |
| | | <ClCompile Include="..\reverb.cpp" /> |
| | | <ClCompile Include="..\reverb_utils\Biquad.cpp" /> |
| | | <ClCompile Include="..\reverb_utils\Parameters.cpp" /> |
| | | <ClCompile Include="..\reverb_utils\RandomBuffer.cpp" /> |
| | | <ClCompile Include="..\reverb_wrapper.c" /> |
| | | <ClCompile Include="ReverbHallRoom.cpp" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ClInclude Include="..\dr_wav.h" /> |
| | | <ClInclude Include="..\reverb.h" /> |
| | | <ClInclude Include="..\reverb_utils\AllpassDiffuser.h" /> |
| | | <ClInclude Include="..\reverb_utils\Biquad.h" /> |
| | | <ClInclude Include="..\reverb_utils\DelayLine.h" /> |
| | | <ClInclude Include="..\reverb_utils\Hp1.h" /> |
| | | <ClInclude Include="..\reverb_utils\LcgRandom.h" /> |
| | | <ClInclude Include="..\reverb_utils\Lp1.h" /> |
| | | <ClInclude Include="..\reverb_utils\ModulatedAllpass.h" /> |
| | | <ClInclude Include="..\reverb_utils\ModulatedDelay.h" /> |
| | | <ClInclude Include="..\reverb_utils\MultitapDelay.h" /> |
| | | <ClInclude Include="..\reverb_utils\Parameters.h" /> |
| | | <ClInclude Include="..\reverb_utils\Programs.h" /> |
| | | <ClInclude Include="..\reverb_utils\RandomBuffer.h" /> |
| | | <ClInclude Include="..\reverb_utils\ReverbChannel.h" /> |
| | | <ClInclude Include="..\reverb_utils\ReverbController.h" /> |
| | | <ClInclude Include="..\reverb_utils\Utils.h" /> |
| | | <ClInclude Include="..\reverb_wrapper.h" /> |
| | | </ItemGroup> |
| | | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> |
| | | <ImportGroup Label="ExtensionTargets"> |
| | | </ImportGroup> |
| | | </Project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
| | | <ItemGroup> |
| | | <Filter Include="æºæä»¶"> |
| | | <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> |
| | | <Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions> |
| | | </Filter> |
| | | <Filter Include="头æä»¶"> |
| | | <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> |
| | | <Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions> |
| | | </Filter> |
| | | <Filter Include="èµæºæä»¶"> |
| | | <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> |
| | | <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> |
| | | </Filter> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ClCompile Include="ReverbHallRoom.cpp"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClCompile> |
| | | <ClCompile Include="..\reverb.cpp"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClCompile> |
| | | <ClCompile Include="..\reverb_wrapper.c"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClCompile> |
| | | <ClCompile Include="..\reverb_utils\Biquad.cpp"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClCompile> |
| | | <ClCompile Include="..\reverb_utils\Parameters.cpp"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClCompile> |
| | | <ClCompile Include="..\reverb_utils\RandomBuffer.cpp"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClCompile> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ClInclude Include="..\reverb_utils\AllpassDiffuser.h"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClInclude> |
| | | <ClInclude Include="..\reverb_utils\Biquad.h"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClInclude> |
| | | <ClInclude Include="..\reverb_utils\DelayLine.h"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClInclude> |
| | | <ClInclude Include="..\reverb_utils\Hp1.h"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClInclude> |
| | | <ClInclude Include="..\reverb_utils\LcgRandom.h"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClInclude> |
| | | <ClInclude Include="..\reverb_utils\Lp1.h"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClInclude> |
| | | <ClInclude Include="..\reverb_utils\ModulatedAllpass.h"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClInclude> |
| | | <ClInclude Include="..\reverb_utils\ModulatedDelay.h"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClInclude> |
| | | <ClInclude Include="..\reverb_utils\MultitapDelay.h"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClInclude> |
| | | <ClInclude Include="..\reverb_utils\Parameters.h"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClInclude> |
| | | <ClInclude Include="..\reverb_utils\Programs.h"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClInclude> |
| | | <ClInclude Include="..\reverb_utils\RandomBuffer.h"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClInclude> |
| | | <ClInclude Include="..\reverb_utils\ReverbChannel.h"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClInclude> |
| | | <ClInclude Include="..\reverb_utils\ReverbController.h"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClInclude> |
| | | <ClInclude Include="..\reverb_utils\Utils.h"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClInclude> |
| | | <ClInclude Include="..\reverb.h"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClInclude> |
| | | <ClInclude Include="..\reverb_wrapper.h"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClInclude> |
| | | <ClInclude Include="..\dr_wav.h"> |
| | | <Filter>æºæä»¶</Filter> |
| | | </ClInclude> |
| | | </ItemGroup> |
| | | </Project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
| | | <PropertyGroup /> |
| | | </Project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | e:\adi_prj\z_git_fold_temp\03-audio_process\cbb_roomreverb\reverbhallroom\reverbhallroom\x64\debug\vc143.pdb |
| | | e:\adi_prj\z_git_fold_temp\03-audio_process\cbb_roomreverb\reverbhallroom\reverbhallroom\x64\debug\vc143.idb |
| | | e:\adi_prj\z_git_fold_temp\03-audio_process\cbb_roomreverb\reverbhallroom\reverbhallroom\x64\debug\reverbhallroom.obj |
| | | e:\adi_prj\z_git_fold_temp\03-audio_process\cbb_roomreverb\reverbhallroom\reverbhallroom\x64\debug\randombuffer.obj |
| | | e:\adi_prj\z_git_fold_temp\03-audio_process\cbb_roomreverb\reverbhallroom\reverbhallroom\x64\debug\parameters.obj |
| | | e:\adi_prj\z_git_fold_temp\03-audio_process\cbb_roomreverb\reverbhallroom\reverbhallroom\x64\debug\biquad.obj |
| | | e:\adi_prj\z_git_fold_temp\03-audio_process\cbb_roomreverb\reverbhallroom\reverbhallroom\x64\debug\reverb.obj |
| | | e:\adi_prj\z_git_fold_temp\03-audio_process\cbb_roomreverb\reverbhallroom\reverbhallroom\x64\debug\reverb_wrapper.obj |
| | | e:\adi_prj\z_git_fold_temp\03-audio_process\cbb_roomreverb\reverbhallroom\x64\debug\reverbhallroom.exe |
| | | e:\adi_prj\z_git_fold_temp\03-audio_process\cbb_roomreverb\reverbhallroom\x64\debug\reverbhallroom.pdb |
| | | e:\adi_prj\z_git_fold_temp\03-audio_process\cbb_roomreverb\reverbhallroom\reverbhallroom\x64\debug\reverbhallroom.ilk |
| | | e:\adi_prj\z_git_fold_temp\03-audio_process\cbb_roomreverb\reverbhallroom\reverbhallroom\x64\debug\reverbhallroom.tlog\cl.command.1.tlog |
| | | e:\adi_prj\z_git_fold_temp\03-audio_process\cbb_roomreverb\reverbhallroom\reverbhallroom\x64\debug\reverbhallroom.tlog\cl.items.tlog |
| | | e:\adi_prj\z_git_fold_temp\03-audio_process\cbb_roomreverb\reverbhallroom\reverbhallroom\x64\debug\reverbhallroom.tlog\cl.read.1.tlog |
| | | e:\adi_prj\z_git_fold_temp\03-audio_process\cbb_roomreverb\reverbhallroom\reverbhallroom\x64\debug\reverbhallroom.tlog\cl.write.1.tlog |
| | | e:\adi_prj\z_git_fold_temp\03-audio_process\cbb_roomreverb\reverbhallroom\reverbhallroom\x64\debug\reverbhallroom.tlog\link.command.1.tlog |
| | | e:\adi_prj\z_git_fold_temp\03-audio_process\cbb_roomreverb\reverbhallroom\reverbhallroom\x64\debug\reverbhallroom.tlog\link.read.1.tlog |
| | | e:\adi_prj\z_git_fold_temp\03-audio_process\cbb_roomreverb\reverbhallroom\reverbhallroom\x64\debug\reverbhallroom.tlog\link.secondary.1.tlog |
| | | e:\adi_prj\z_git_fold_temp\03-audio_process\cbb_roomreverb\reverbhallroom\reverbhallroom\x64\debug\reverbhallroom.tlog\link.write.1.tlog |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="utf-8"?> |
| | | <Project> |
| | | <ProjectOutputs> |
| | | <ProjectOutput> |
| | | <FullPath>E:\ADI_Prj\z_git_fold_temp\03-audio_process\cbb_RoomReverb\ReverbHallRoom\x64\Debug\ReverbHallRoom.exe</FullPath> |
| | | </ProjectOutput> |
| | | </ProjectOutputs> |
| | | <ContentFiles /> |
| | | <SatelliteDlls /> |
| | | <NonRecipeFileRefs /> |
| | | </Project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | FS:48000, CH:1, N:64, Reverb Params: |
| | | Dry: MUTED |
| | | Early: MUTED |
| | | Late: -6.0 dB |
| | | Interpolation: DISABLED |
| | | High_Cut_ON: DISABLED |
| | | Low_Cut_ON: DISABLED |
| | | Input Mix: 0% |
| | | High Cut: 400 Hz |
| | | Low Cut: 20 Hz |
| | | Cross Seed: 0% |
| | | |
| | | Multitap_Delay_ON: ENABLED |
| | | Count: 128 |
| | | Pre-delay: 32 ms |
| | | Decay: 50% |
| | | Length: 109 ms |
| | | |
| | | Early_Diffusion_ON: ENABLED |
| | | Diffusion Stages: 6 |
| | | Delay: 10 ms |
| | | Feedback: 30% |
| | | Mod Amt: 50% |
| | | Mod Rate: 0.03 Hz |
| | | |
| | | Late_Mode: POST |
| | | Late_Diffusion_ON: ENABLED |
| | | Line_Count: 4 |
| | | Line_Size: 72 ms |
| | | Line_Mod_Amt: 50% |
| | | Line_Decay: 109 ms |
| | | Line_Mod_Rate: 0.00 Hz |
| | | Diffusion Stages: 1 |
| | | Diffusion_Delay: 28 ms |
| | | Diffusion_Feedback: 30% |
| | | Diffusion_Mod Amt: 75% |
| | | Diffusion_Mod Rate: 0.27 Hz |
| | | |
| | | EQ_Low_Shelf_ON: DISABLED |
| | | EQ_High_Shelf_ON: DISABLED |
| | | EQ_Lowpass_ON: DISABLED |
| | | Low_Freq: 20 Hz |
| | | Low Gain: -18.0 dB |
| | | High Freq: 817 Hz |
| | | High Gain: -18.0 dB |
| | | LP_Cutoff_Freq: 1368 Hz |
| | | |
| | | Tap Seed: 499 |
| | | Diffusion Seed: 499 |
| | | Delay Seed: 499 |
| | | Late Diffusion Seed: 499 |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | |
| | | #pragma once |
| | | |
| | | #include <vector> |
| | | #include "ModulatedAllpass.h" |
| | | #include "RandomBuffer.h" |
| | | |
| | | |
| | | #ifndef BUFFER_SIZE |
| | | #define BUFFER_SIZE 1024 |
| | | #endif |
| | | |
| | | |
| | | |
| | | namespace ReverbHallRoom |
| | | { |
| | | class AllpassDiffuser |
| | | { |
| | | public: |
| | | static const int MaxStageCount = 12; |
| | | |
| | | private: |
| | | int samplerate; |
| | | |
| | | ModulatedAllpass filters[MaxStageCount]; |
| | | int delay; |
| | | float modRate; |
| | | std::vector<float> seedValues; |
| | | int seed; |
| | | float crossSeed; |
| | | |
| | | public: |
| | | int Stages; |
| | | |
| | | AllpassDiffuser() |
| | | { |
| | | crossSeed = 0.0; |
| | | seed = 23456; |
| | | UpdateSeeds(); |
| | | Stages = 1; |
| | | |
| | | SetSamplerate(48000); |
| | | } |
| | | |
| | | int GetSamplerate() |
| | | { |
| | | return samplerate; |
| | | } |
| | | |
| | | void SetSamplerate(int samplerate) |
| | | { |
| | | this->samplerate = samplerate; |
| | | SetModRate(modRate); |
| | | } |
| | | |
| | | void SetSeed(int seed) |
| | | { |
| | | this->seed = seed; |
| | | UpdateSeeds(); |
| | | } |
| | | |
| | | void SetCrossSeed(float crossSeed) |
| | | { |
| | | this->crossSeed = crossSeed; |
| | | UpdateSeeds(); |
| | | } |
| | | |
| | | |
| | | bool GetModulationEnabled() |
| | | { |
| | | return filters[0].ModulationEnabled; |
| | | } |
| | | |
| | | void SetModulationEnabled(bool value) |
| | | { |
| | | for (int i = 0; i < MaxStageCount; i++) |
| | | filters[i].ModulationEnabled = value; |
| | | |
| | | } |
| | | |
| | | void SetInterpolationEnabled(bool enabled) |
| | | { |
| | | for (int i = 0; i < MaxStageCount; i++) |
| | | filters[i].InterpolationEnabled = enabled; |
| | | } |
| | | |
| | | void SetDelay(int delaySamples) |
| | | { |
| | | delay = delaySamples; |
| | | Update(); |
| | | } |
| | | |
| | | void SetFeedback(float feedback) |
| | | { |
| | | for (int i = 0; i < MaxStageCount; i++) |
| | | filters[i].Feedback = feedback; |
| | | } |
| | | |
| | | void SetModAmount(float amount) |
| | | { |
| | | for (int i = 0; i < MaxStageCount; i++) |
| | | filters[i].ModAmount = amount * (0.85 + 0.3 * seedValues[MaxStageCount + i]); |
| | | } |
| | | |
| | | void SetModRate(float rate) |
| | | { |
| | | modRate = rate; |
| | | |
| | | for (int i = 0; i < MaxStageCount; i++) |
| | | filters[i].ModRate = rate * (0.85 + 0.3 * seedValues[MaxStageCount * 2 + i]) / samplerate; |
| | | } |
| | | |
| | | void Process(float* input, float* output, int bufSize) |
| | | { |
| | | float tempBuffer[BUFFER_SIZE]; |
| | | |
| | | filters[0].Process(input, tempBuffer, bufSize); |
| | | |
| | | for (int i = 1; i < Stages; i++) |
| | | filters[i].Process(tempBuffer, tempBuffer, bufSize); |
| | | |
| | | Utils::Copy(output, tempBuffer, bufSize); |
| | | } |
| | | |
| | | void ClearBuffers() |
| | | { |
| | | for (int i = 0; i < MaxStageCount; i++) |
| | | filters[i].ClearBuffers(); |
| | | } |
| | | |
| | | private: |
| | | void Update() |
| | | { |
| | | for (int i = 0; i < MaxStageCount; i++) |
| | | { |
| | | auto r = seedValues[i]; |
| | | auto d = std::pow(10, r) * 0.1; // 0.1 ... 1.0 |
| | | filters[i].SampleDelay = (int)(delay * d); |
| | | } |
| | | } |
| | | |
| | | void UpdateSeeds() |
| | | { |
| | | this->seedValues = RandomBuffer::Generate(seed, MaxStageCount * 3, crossSeed); |
| | | Update(); |
| | | } |
| | | |
| | | }; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | |
| | | #include "Biquad.h" |
| | | #define _USE_MATH_DEFINES |
| | | #include "math.h" |
| | | |
| | | namespace ReverbHallRoom |
| | | { |
| | | Biquad::Biquad() |
| | | { |
| | | ClearBuffers(); |
| | | } |
| | | |
| | | Biquad::Biquad(FilterType filterType, float fs) |
| | | { |
| | | Type = filterType; |
| | | SetSamplerate(fs); |
| | | |
| | | SetGainDb(0.0f); |
| | | Frequency = (float)(fs * 0.25f); |
| | | SetQ(0.5f); |
| | | ClearBuffers(); |
| | | } |
| | | |
| | | Biquad::~Biquad() |
| | | { |
| | | |
| | | } |
| | | |
| | | |
| | | float Biquad::GetSamplerate() |
| | | { |
| | | return fs; |
| | | } |
| | | |
| | | void Biquad::SetSamplerate(float fs) |
| | | { |
| | | this->fs = fs; |
| | | fsInv = 1.0f / fs; |
| | | Update(); |
| | | } |
| | | |
| | | float Biquad::GetGainDb() |
| | | { |
| | | return gainDB; |
| | | } |
| | | |
| | | float Biquad::GetGain() |
| | | { |
| | | return gain; |
| | | } |
| | | |
| | | void Biquad::SetGainDb (float value) |
| | | { |
| | | // Clamp value between -60 and 60 |
| | | if (value < -60) |
| | | value = -60; |
| | | else if (value > 60) |
| | | value = 60; |
| | | |
| | | gainDB = value; |
| | | gain = powf (10.0f, value / 20.0f); |
| | | } |
| | | |
| | | void Biquad::SetGain (float value) |
| | | { |
| | | if (value < 0.001f) |
| | | value = 0.001f; // -60dB |
| | | else if (value > 1000.0f) |
| | | value = 1000.0f; // 60dB |
| | | |
| | | gain = value; |
| | | gainDB = log10f (gain) * 20; |
| | | } |
| | | |
| | | float Biquad::GetQ() |
| | | { |
| | | return q; |
| | | } |
| | | |
| | | void Biquad::SetQ(float value) |
| | | { |
| | | if (value < 0.001f) |
| | | value = 0.001f; |
| | | q = value; |
| | | } |
| | | |
| | | // this is the newer set of formulas from http://www.earlevel.com/main/2011/01/02/biquad-formulas/ |
| | | // Note that for shelf and peak filters, I had to invert the if/else statements for boost and cut, as |
| | | // I was getting the inverse desired effect, very odd... |
| | | void Biquad::Update() |
| | | { |
| | | auto Fc = Frequency; |
| | | //auto Fs = fs; |
| | | |
| | | auto V = powf(10, fabsf(gainDB) / 20.0f); |
| | | //auto K = tanf(M_PI * Fc / Fs); |
| | | auto K = tanf(M_PI * Fc * fsInv); |
| | | auto Q = q; |
| | | double norm = 1.0; |
| | | |
| | | switch (Type) |
| | | { |
| | | case FilterType::LowPass6db: |
| | | a1 = -expf(-2.0 * M_PI * (Fc * fsInv)); |
| | | b0 = 1.0 + a1; |
| | | b1 = b2 = a2 = 0; |
| | | break; |
| | | case FilterType::HighPass6db: |
| | | a1 = -expf(-2.0 * M_PI * (Fc * fsInv)); |
| | | b0 = a1; |
| | | b1 = -a1; |
| | | b2 = a2 = 0; |
| | | break; |
| | | case FilterType::LowPass: |
| | | norm = 1 / (1 + K / Q + K * K); |
| | | b0 = K * K * norm; |
| | | b1 = 2 * b0; |
| | | b2 = b0; |
| | | a1 = 2 * (K * K - 1) * norm; |
| | | a2 = (1 - K / Q + K * K) * norm; |
| | | break; |
| | | case FilterType::HighPass: |
| | | norm = 1 / (1 + K / Q + K * K); |
| | | b0 = 1 * norm; |
| | | b1 = -2 * b0; |
| | | b2 = b0; |
| | | a1 = 2 * (K * K - 1) * norm; |
| | | a2 = (1 - K / Q + K * K) * norm; |
| | | break; |
| | | case FilterType::BandPass: |
| | | norm = 1 / (1 + K / Q + K * K); |
| | | b0 = K / Q * norm; |
| | | b1 = 0; |
| | | b2 = -b0; |
| | | a1 = 2 * (K * K - 1) * norm; |
| | | a2 = (1 - K / Q + K * K) * norm; |
| | | break; |
| | | case FilterType::Notch: |
| | | norm = 1 / (1 + K / Q + K * K); |
| | | b0 = (1 + K * K) * norm; |
| | | b1 = 2 * (K * K - 1) * norm; |
| | | b2 = b0; |
| | | a1 = b1; |
| | | a2 = (1 - K / Q + K * K) * norm; |
| | | break; |
| | | case FilterType::Peak: |
| | | if (gainDB >= 0) |
| | | { |
| | | norm = 1 / (1 + 1 / Q * K + K * K); |
| | | b0 = (1 + V / Q * K + K * K) * norm; |
| | | b1 = 2 * (K * K - 1) * norm; |
| | | b2 = (1 - V / Q * K + K * K) * norm; |
| | | a1 = b1; |
| | | a2 = (1 - 1 / Q * K + K * K) * norm; |
| | | } |
| | | else |
| | | { |
| | | norm = 1 / (1 + V / Q * K + K * K); |
| | | b0 = (1 + 1 / Q * K + K * K) * norm; |
| | | b1 = 2 * (K * K - 1) * norm; |
| | | b2 = (1 - 1 / Q * K + K * K) * norm; |
| | | a1 = b1; |
| | | a2 = (1 - V / Q * K + K * K) * norm; |
| | | } |
| | | break; |
| | | case FilterType::LowShelf: |
| | | if (gainDB >= 0) |
| | | { |
| | | norm = 1 / (1 + sqrtf(2) * K + K * K); |
| | | b0 = (1 + sqrtf(2 * V) * K + V * K * K) * norm; |
| | | b1 = 2 * (V * K * K - 1) * norm; |
| | | b2 = (1 - sqrtf(2 * V) * K + V * K * K) * norm; |
| | | a1 = 2 * (K * K - 1) * norm; |
| | | a2 = (1 - sqrtf(2) * K + K * K) * norm; |
| | | } |
| | | else |
| | | { |
| | | norm = 1 / (1 + sqrtf(2 * V) * K + V * K * K); |
| | | b0 = (1 + sqrtf(2) * K + K * K) * norm; |
| | | b1 = 2 * (K * K - 1) * norm; |
| | | b2 = (1 - sqrtf(2) * K + K * K) * norm; |
| | | a1 = 2 * (V * K * K - 1) * norm; |
| | | a2 = (1 - sqrtf(2 * V) * K + V * K * K) * norm; |
| | | } |
| | | break; |
| | | case FilterType::HighShelf: |
| | | if (gainDB >= 0) |
| | | { |
| | | norm = 1 / (1 + sqrtf(2) * K + K * K); |
| | | b0 = (V + sqrtf(2 * V) * K + K * K) * norm; |
| | | b1 = 2 * (K * K - V) * norm; |
| | | b2 = (V - sqrtf(2 * V) * K + K * K) * norm; |
| | | a1 = 2 * (K * K - 1) * norm; |
| | | a2 = (1 - sqrtf(2) * K + K * K) * norm; |
| | | } |
| | | else |
| | | { |
| | | norm = 1 / (V + sqrtf(2 * V) * K + K * K); |
| | | b0 = (1 + sqrtf(2) * K + K * K) * norm; |
| | | b1 = 2 * (K * K - 1) * norm; |
| | | b2 = (1 - sqrtf(2) * K + K * K) * norm; |
| | | a1 = 2 * (K * K - V) * norm; |
| | | a2 = (V - sqrtf(2 * V) * K + K * K) * norm; |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | |
| | | double Biquad::GetResponse(float freq) const |
| | | { |
| | | double phi = powf((sinf(2 * M_PI * freq / (2.0 * fs))), 2); |
| | | double y = ((powf(b0 + b1 + b2, 2.0) - 4.0 * (b0 * b1 + 4.0 * b0 * b2 + b1 * b2) * phi + 16.0 * b0 * b2 * phi * phi) / (powf(1.0 + a1 + a2, 2.0) - 4.0 * (a1 + 4.0 * a2 + a1 * a2) * phi + 16.0 * a2 * phi * phi)); |
| | | // y gives you power gain, not voltage gain, and this a 10 * log_10(g) formula instead of 20 * log_10(g) |
| | | // by taking the sqrt we get a value that's more suitable for signal processing, i.e. the voltage gain |
| | | return sqrtf(y); |
| | | } |
| | | |
| | | void Biquad::ClearBuffers() |
| | | { |
| | | y = 0; |
| | | x2 = 0; |
| | | y2 = 0; |
| | | x1 = 0; |
| | | y1 = 0; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | |
| | | #pragma once |
| | | |
| | | namespace ReverbHallRoom |
| | | { |
| | | class Biquad |
| | | { |
| | | public: |
| | | enum class FilterType |
| | | { |
| | | LowPass6db = 0, |
| | | HighPass6db, |
| | | LowPass, |
| | | HighPass, |
| | | BandPass, |
| | | Notch, |
| | | Peak, |
| | | LowShelf, |
| | | HighShelf |
| | | }; |
| | | |
| | | private: |
| | | float fs; |
| | | float fsInv; |
| | | float gainDB; |
| | | float q; |
| | | float a0, a1, a2, b0, b1, b2; |
| | | float x1, x2, y, y1, y2; |
| | | float gain; |
| | | |
| | | public: |
| | | FilterType Type; |
| | | float Output; |
| | | float Frequency; |
| | | |
| | | Biquad(); |
| | | Biquad(FilterType filterType, float fs); |
| | | ~Biquad(); |
| | | |
| | | float GetSamplerate(); |
| | | void SetSamplerate(float fs); |
| | | float GetGainDb(); |
| | | void SetGainDb(float value); |
| | | float GetGain(); |
| | | void SetGain(float value); |
| | | float GetQ(); |
| | | void SetQ(float value); |
| | | |
| | | void Update(); |
| | | |
| | | double GetResponse(float freq) const; |
| | | |
| | | float inline Process(float x) |
| | | { |
| | | y = b0 * x + b1 * x1 + b2 * x2 - a1 * y1 - a2 * y2; |
| | | x2 = x1; |
| | | y2 = y1; |
| | | x1 = x; |
| | | y1 = y; |
| | | |
| | | Output = y; |
| | | return Output; |
| | | } |
| | | |
| | | void inline Process(float* input, float* output, int len) |
| | | { |
| | | for (int i = 0; i < len; i++) |
| | | { |
| | | float x = input[i]; |
| | | y = ((b0 * x) + (b1 * x1) + (b2 * x2)) - (a1 * y1) - (a2 * y2); |
| | | x2 = x1; |
| | | y2 = y1; |
| | | x1 = x; |
| | | y1 = y; |
| | | |
| | | output[i] = y; |
| | | } |
| | | |
| | | Output = y; |
| | | } |
| | | |
| | | void ClearBuffers(); |
| | | }; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | |
| | | #pragma once |
| | | |
| | | #include "Lp1.h" |
| | | #include "ModulatedDelay.h" |
| | | #include "AllpassDiffuser.h" |
| | | #include "Biquad.h" |
| | | |
| | | namespace ReverbHallRoom |
| | | { |
| | | template<unsigned int N> |
| | | class CircularBuffer |
| | | { |
| | | float buffer[N]; |
| | | int idxRead; |
| | | int idxWrite; |
| | | int count; |
| | | public: |
| | | CircularBuffer() |
| | | { |
| | | Reset(); |
| | | } |
| | | |
| | | void Reset() |
| | | { |
| | | for (int i = 0; i < N; i++) |
| | | buffer[i] = 0.0f; |
| | | idxRead = 0; |
| | | idxWrite = 0; |
| | | count = 0; |
| | | } |
| | | |
| | | int GetCount() |
| | | { |
| | | return count; |
| | | } |
| | | |
| | | int PushZeros(float* data, int bufSize) |
| | | { |
| | | int countBefore = count; |
| | | for (int i = 0; i < bufSize; i++) |
| | | { |
| | | buffer[idxWrite] = 0.0f; |
| | | idxWrite = (idxWrite + 1) % N; |
| | | count++; |
| | | if (count >= N) |
| | | break; // overflow |
| | | } |
| | | |
| | | return count - countBefore; |
| | | } |
| | | |
| | | int Push(float* data, int bufSize) |
| | | { |
| | | int countBefore = count; |
| | | for (int i = 0; i < bufSize; i++) |
| | | { |
| | | buffer[idxWrite] = data[i]; |
| | | idxWrite = (idxWrite + 1) % N; |
| | | count++; |
| | | if (count >= N) |
| | | break; // overflow |
| | | } |
| | | |
| | | return count - countBefore; |
| | | } |
| | | |
| | | int Pop(float* destination, int bufSize) |
| | | { |
| | | int countBefore = count; |
| | | for (int i = 0; i < bufSize; i++) |
| | | { |
| | | if (count > 0) |
| | | { |
| | | destination[i] = buffer[idxRead]; |
| | | idxRead = (idxRead + 1) % N; |
| | | count--; |
| | | } |
| | | else |
| | | { |
| | | destination[i] = 0.0f; |
| | | } |
| | | } |
| | | |
| | | return countBefore - count; |
| | | } |
| | | |
| | | }; |
| | | |
| | | class DelayLine |
| | | { |
| | | private: |
| | | ModulatedDelay delay; |
| | | AllpassDiffuser diffuser; |
| | | Biquad lowShelf; |
| | | Biquad highShelf; |
| | | Lp1 lowPass; |
| | | CircularBuffer<2*BUFFER_SIZE> feedbackBuffer; |
| | | float feedback; |
| | | |
| | | public: |
| | | bool DiffuserEnabled; |
| | | bool LowShelfEnabled; |
| | | bool HighShelfEnabled; |
| | | bool CutoffEnabled; |
| | | bool TapPostDiffuser; |
| | | |
| | | DelayLine() : |
| | | lowShelf(Biquad::FilterType::LowShelf, 48000), |
| | | highShelf(Biquad::FilterType::HighShelf, 48000) |
| | | { |
| | | feedback = 0; |
| | | |
| | | lowShelf.SetGainDb(-20); |
| | | lowShelf.Frequency = 20; |
| | | |
| | | highShelf.SetGainDb(-20); |
| | | highShelf.Frequency = 19000; |
| | | |
| | | lowPass.SetCutoffHz(1000); |
| | | lowShelf.Update(); |
| | | highShelf.Update(); |
| | | SetSamplerate(48000); |
| | | SetDiffuserSeed(1, 0.0); |
| | | } |
| | | |
| | | void SetSamplerate(int samplerate) |
| | | { |
| | | diffuser.SetSamplerate(samplerate); |
| | | lowPass.SetSamplerate(samplerate); |
| | | lowShelf.SetSamplerate(samplerate); |
| | | highShelf.SetSamplerate(samplerate); |
| | | } |
| | | |
| | | void SetDiffuserSeed(int seed, float crossSeed) |
| | | { |
| | | diffuser.SetSeed(seed); |
| | | diffuser.SetCrossSeed(crossSeed); |
| | | } |
| | | |
| | | void SetDelay(int delaySamples) |
| | | { |
| | | delay.SampleDelay = delaySamples; |
| | | } |
| | | |
| | | void SetFeedback(float feedb) |
| | | { |
| | | feedback = feedb; |
| | | } |
| | | |
| | | void SetDiffuserDelay(int delaySamples) |
| | | { |
| | | diffuser.SetDelay(delaySamples); |
| | | } |
| | | |
| | | void SetDiffuserFeedback(float feedb) |
| | | { |
| | | diffuser.SetFeedback(feedb); |
| | | } |
| | | |
| | | void SetDiffuserStages(int stages) |
| | | { |
| | | diffuser.Stages = stages; |
| | | } |
| | | |
| | | void SetLowShelfGain(float gainDb) |
| | | { |
| | | lowShelf.SetGainDb(gainDb); |
| | | lowShelf.Update(); |
| | | } |
| | | |
| | | void SetLowShelfFrequency(float frequency) |
| | | { |
| | | lowShelf.Frequency = frequency; |
| | | lowShelf.Update(); |
| | | } |
| | | |
| | | void SetHighShelfGain(float gainDb) |
| | | { |
| | | highShelf.SetGainDb(gainDb); |
| | | highShelf.Update(); |
| | | } |
| | | |
| | | void SetHighShelfFrequency(float frequency) |
| | | { |
| | | highShelf.Frequency = frequency; |
| | | highShelf.Update(); |
| | | } |
| | | |
| | | void SetCutoffFrequency(float frequency) |
| | | { |
| | | lowPass.SetCutoffHz(frequency); |
| | | } |
| | | |
| | | void SetLineModAmount(float amount) |
| | | { |
| | | delay.ModAmount = amount; |
| | | } |
| | | |
| | | void SetLineModRate(float rate) |
| | | { |
| | | delay.ModRate = rate; |
| | | } |
| | | |
| | | void SetDiffuserModAmount(float amount) |
| | | { |
| | | diffuser.SetModulationEnabled(amount > 0.0); |
| | | diffuser.SetModAmount(amount); |
| | | } |
| | | |
| | | void SetDiffuserModRate(float rate) |
| | | { |
| | | diffuser.SetModRate(rate); |
| | | } |
| | | |
| | | void SetInterpolationEnabled(bool value) |
| | | { |
| | | diffuser.SetInterpolationEnabled(value); |
| | | } |
| | | |
| | | void Process(float* input, float* output, int bufSize) |
| | | { |
| | | float tempBuffer[BUFFER_SIZE]; |
| | | feedbackBuffer.Pop(tempBuffer, bufSize); |
| | | |
| | | for (int i = 0; i < bufSize; i++) |
| | | tempBuffer[i] = input[i] + tempBuffer[i] * feedback; |
| | | |
| | | delay.Process(tempBuffer, tempBuffer, bufSize); |
| | | |
| | | if (!TapPostDiffuser) |
| | | Utils::Copy(output, tempBuffer, bufSize); |
| | | if (DiffuserEnabled) |
| | | diffuser.Process(tempBuffer, tempBuffer, bufSize); |
| | | if (LowShelfEnabled) |
| | | lowShelf.Process(tempBuffer, tempBuffer, bufSize); |
| | | if (HighShelfEnabled) |
| | | highShelf.Process(tempBuffer, tempBuffer, bufSize); |
| | | if (CutoffEnabled) |
| | | lowPass.Process(tempBuffer, tempBuffer, bufSize); |
| | | |
| | | feedbackBuffer.Push(tempBuffer, bufSize); |
| | | |
| | | if (TapPostDiffuser) |
| | | Utils::Copy(output, tempBuffer, bufSize); |
| | | } |
| | | |
| | | void ClearDiffuserBuffer() |
| | | { |
| | | diffuser.ClearBuffers(); |
| | | } |
| | | |
| | | void ClearBuffers() |
| | | { |
| | | delay.ClearBuffers(); |
| | | diffuser.ClearBuffers(); |
| | | lowShelf.ClearBuffers(); |
| | | highShelf.ClearBuffers(); |
| | | lowPass.Output = 0; |
| | | feedbackBuffer.Reset(); |
| | | } |
| | | }; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | |
| | | #pragma once |
| | | |
| | | #define _USE_MATH_DEFINES |
| | | #include <cmath> |
| | | |
| | | namespace ReverbHallRoom |
| | | { |
| | | class Hp1 |
| | | { |
| | | private: |
| | | float fs; |
| | | float b0, a1; |
| | | float lpOut; |
| | | float cutoffHz; |
| | | |
| | | public: |
| | | float Output; |
| | | |
| | | Hp1() |
| | | { |
| | | fs = 48000; |
| | | b0 = 1; |
| | | a1 = 0; |
| | | lpOut = 0.0; |
| | | cutoffHz = 100; |
| | | } |
| | | |
| | | float GetSamplerate() |
| | | { |
| | | return fs; |
| | | } |
| | | |
| | | void SetSamplerate(float samplerate) |
| | | { |
| | | fs = samplerate; |
| | | } |
| | | |
| | | float GetCutoffHz() |
| | | { |
| | | return cutoffHz; |
| | | } |
| | | |
| | | void SetCutoffHz(float hz) |
| | | { |
| | | cutoffHz = hz; |
| | | Update(); |
| | | } |
| | | |
| | | void ClearBuffers() |
| | | { |
| | | lpOut = 0; |
| | | Output = 0; |
| | | } |
| | | |
| | | void Update() |
| | | { |
| | | // Prevent going over the Nyquist frequency |
| | | if (cutoffHz >= fs * 0.5f) |
| | | cutoffHz = fs * 0.499f; |
| | | |
| | | auto x = 2.0f * M_PI * cutoffHz / fs; |
| | | auto nn = (2.0f - cosf(x)); |
| | | auto alpha = nn - sqrtf(nn * nn - 1); |
| | | |
| | | a1 = alpha; |
| | | b0 = 1 - alpha; |
| | | } |
| | | |
| | | float Process(float input) |
| | | { |
| | | if (input == 0 && lpOut < 0.000001f) |
| | | { |
| | | Output = 0; |
| | | } |
| | | else |
| | | { |
| | | lpOut = b0 * input + a1 * lpOut; |
| | | Output = input - lpOut; |
| | | } |
| | | |
| | | return Output; |
| | | } |
| | | |
| | | void Process(float* input, float* output, int len) |
| | | { |
| | | for (int i = 0; i < len; i++) |
| | | output[i] = Process(input[i]); |
| | | } |
| | | }; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | |
| | | #pragma once |
| | | |
| | | #include <stdint.h> |
| | | |
| | | namespace ReverbHallRoom |
| | | { |
| | | class LcgRandom |
| | | { |
| | | private: |
| | | uint64_t x; |
| | | uint64_t a; |
| | | uint64_t c; |
| | | |
| | | double doubleInv; |
| | | float floatUintInv; |
| | | float floatIntInv; |
| | | |
| | | public: |
| | | inline LcgRandom(uint64_t seed = 0) |
| | | { |
| | | x = seed; |
| | | a = 22695477; |
| | | c = 1; |
| | | |
| | | doubleInv = 1.0 / (double)UINT32_MAX; |
| | | floatUintInv = 1.0 / (float)UINT32_MAX; |
| | | floatIntInv = 1.0 / (float)INT32_MAX; |
| | | } |
| | | |
| | | inline void SetSeed(uint64_t seed) |
| | | { |
| | | x = seed; |
| | | } |
| | | |
| | | inline uint32_t NextUInt() |
| | | { |
| | | uint64_t axc = a * x + c; |
| | | //x = axc % m; |
| | | x = axc & 0xFFFFFFFF; |
| | | return (uint32_t)x; |
| | | } |
| | | |
| | | inline int32_t NextInt() |
| | | { |
| | | int64_t axc = a * x + c; |
| | | //x = axc % m; |
| | | x = axc & 0x7FFFFFFF; |
| | | return (int32_t)x; |
| | | } |
| | | |
| | | inline double NextDouble() |
| | | { |
| | | auto n = NextUInt(); |
| | | return n * doubleInv; |
| | | } |
| | | |
| | | inline float NextFloat() |
| | | { |
| | | auto n = NextInt(); |
| | | return n * floatIntInv; |
| | | } |
| | | |
| | | inline void GetFloats(float* buffer, int len) |
| | | { |
| | | for (int i = 0; i < len; i++) |
| | | buffer[i] = NextFloat(); |
| | | } |
| | | |
| | | inline void GetFloatsBipolar(float* buffer, int len) |
| | | { |
| | | for (int i = 0; i < len; i++) |
| | | buffer[i] = NextFloat() * 2 - 1; |
| | | } |
| | | }; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | |
| | | #pragma once |
| | | |
| | | #define _USE_MATH_DEFINES |
| | | #include <cmath> |
| | | |
| | | namespace ReverbHallRoom |
| | | { |
| | | class Lp1 |
| | | { |
| | | private: |
| | | float fs; |
| | | float b0, a1; |
| | | float cutoffHz; |
| | | |
| | | public: |
| | | float Output; |
| | | |
| | | Lp1() |
| | | { |
| | | fs = 48000; |
| | | b0 = 1; |
| | | a1 = 0; |
| | | cutoffHz = 1000; |
| | | } |
| | | |
| | | float GetSamplerate() |
| | | { |
| | | return fs; |
| | | } |
| | | |
| | | void SetSamplerate(float samplerate) |
| | | { |
| | | fs = samplerate; |
| | | } |
| | | |
| | | float GetCutoffHz() |
| | | { |
| | | return cutoffHz; |
| | | } |
| | | |
| | | void SetCutoffHz(float hz) |
| | | { |
| | | cutoffHz = hz; |
| | | Update(); |
| | | } |
| | | |
| | | void ClearBuffers() |
| | | { |
| | | Output = 0; |
| | | } |
| | | |
| | | void Update() |
| | | { |
| | | // Prevent going over the Nyquist frequency |
| | | if (cutoffHz >= fs * 0.5f) |
| | | cutoffHz = fs * 0.499f; |
| | | |
| | | auto x = 2.0f * M_PI * cutoffHz / fs; |
| | | auto nn = (2.0f - cosf(x)); |
| | | auto alpha = nn - sqrtf(nn * nn - 1); |
| | | |
| | | a1 = alpha; |
| | | b0 = 1 - alpha; |
| | | } |
| | | |
| | | float Process(float input) |
| | | { |
| | | if (input == 0 && Output < 0.0000001f) |
| | | { |
| | | Output = 0; |
| | | } |
| | | else |
| | | { |
| | | Output = b0 * input + a1 * Output; |
| | | } |
| | | return Output; |
| | | } |
| | | |
| | | void Process(float* input, float* output, int len) |
| | | { |
| | | for (int i = 0; i < len; i++) |
| | | output[i] = Process(input[i]); |
| | | } |
| | | }; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | |
| | | #pragma once |
| | | |
| | | #include "ModulatedAllpass.h" |
| | | #include "Utils.h" |
| | | #include <cmath> |
| | | |
| | | namespace ReverbHallRoom |
| | | { |
| | | class ModulatedAllpass |
| | | { |
| | | public: |
| | | static const int DelayBufferSize = 19200; // 100ms at 192Khz |
| | | static const int ModulationUpdateRate = 8; |
| | | |
| | | private: |
| | | //float delayBuffer[DelayBufferSize] = { 0 }; |
| | | std::vector<float> delayBuffer; |
| | | |
| | | int index; |
| | | uint64_t samplesProcessed; |
| | | |
| | | float modPhase; |
| | | int delayA; |
| | | int delayB; |
| | | float gainA; |
| | | float gainB; |
| | | |
| | | public: |
| | | |
| | | int SampleDelay; |
| | | float Feedback; |
| | | float ModAmount; |
| | | float ModRate; |
| | | |
| | | bool InterpolationEnabled; |
| | | bool ModulationEnabled; |
| | | |
| | | ModulatedAllpass() : delayBuffer(DelayBufferSize, 0) |
| | | { |
| | | index = DelayBufferSize - 1; |
| | | samplesProcessed = 0; |
| | | |
| | | modPhase = 0.01 + 0.98 * std::rand() / (float)RAND_MAX; |
| | | delayA = 0; |
| | | delayB = 0; |
| | | gainA = 0; |
| | | gainB = 0; |
| | | |
| | | SampleDelay = 100; |
| | | Feedback = 0.5; |
| | | ModAmount = 0.0; |
| | | ModRate = 0.0; |
| | | |
| | | InterpolationEnabled = true; |
| | | ModulationEnabled = true; |
| | | Update(); |
| | | } |
| | | |
| | | void ClearBuffers() |
| | | { |
| | | Utils::ZeroBuffer(delayBuffer.data(), DelayBufferSize); |
| | | } |
| | | |
| | | void Process(float* input, float* output, int sampleCount) |
| | | { |
| | | if (ModulationEnabled) |
| | | ProcessWithMod(input, output, sampleCount); |
| | | else |
| | | ProcessNoMod(input, output, sampleCount); |
| | | } |
| | | |
| | | private: |
| | | void ProcessNoMod(float* input, float* output, int sampleCount) |
| | | { |
| | | auto delayedIndex = index - SampleDelay; |
| | | if (delayedIndex < 0) delayedIndex += DelayBufferSize; |
| | | |
| | | for (int i = 0; i < sampleCount; i++) |
| | | { |
| | | auto bufOut = delayBuffer[delayedIndex]; |
| | | auto inVal = input[i] + bufOut * Feedback; |
| | | |
| | | delayBuffer[index] = inVal; |
| | | output[i] = bufOut - inVal * Feedback; |
| | | |
| | | index++; |
| | | delayedIndex++; |
| | | if (index >= DelayBufferSize) index -= DelayBufferSize; |
| | | if (delayedIndex >= DelayBufferSize) delayedIndex -= DelayBufferSize; |
| | | samplesProcessed++; |
| | | } |
| | | } |
| | | |
| | | void ProcessWithMod(float* input, float* output, int sampleCount) |
| | | { |
| | | for (int i = 0; i < sampleCount; i++) |
| | | { |
| | | if (samplesProcessed >= ModulationUpdateRate) |
| | | { |
| | | Update(); |
| | | samplesProcessed = 0; |
| | | } |
| | | |
| | | float bufOut; |
| | | |
| | | if (InterpolationEnabled) |
| | | { |
| | | int idxA = index - delayA; |
| | | int idxB = index - delayB; |
| | | idxA += DelayBufferSize * (idxA < 0); // modulo |
| | | idxB += DelayBufferSize * (idxB < 0); // modulo |
| | | |
| | | bufOut = delayBuffer[idxA] * gainA + delayBuffer[idxB] * gainB; |
| | | } |
| | | else |
| | | { |
| | | int idxA = index - delayA; |
| | | idxA += DelayBufferSize * (idxA < 0); // modulo |
| | | bufOut = delayBuffer[idxA]; |
| | | } |
| | | |
| | | auto inVal = input[i] + bufOut * Feedback; |
| | | delayBuffer[index] = inVal; |
| | | output[i] = bufOut - inVal * Feedback; |
| | | |
| | | index++; |
| | | if (index >= DelayBufferSize) index -= DelayBufferSize; |
| | | samplesProcessed++; |
| | | } |
| | | } |
| | | |
| | | inline float Get(int delay) |
| | | { |
| | | int idx = index - delay; |
| | | if (idx < 0) |
| | | idx += DelayBufferSize; |
| | | |
| | | return delayBuffer[idx]; |
| | | } |
| | | |
| | | void Update() |
| | | { |
| | | modPhase += ModRate * ModulationUpdateRate; |
| | | if (modPhase > 1) |
| | | modPhase = std::fmod(modPhase, 1.0); |
| | | |
| | | auto mod = std::sinf(modPhase * 2 * M_PI); |
| | | |
| | | if (ModAmount >= SampleDelay) // don't modulate to negative value |
| | | ModAmount = SampleDelay - 1; |
| | | |
| | | |
| | | auto totalDelay = SampleDelay + ModAmount * mod; |
| | | |
| | | if (totalDelay <= 0) // should no longer be required |
| | | totalDelay = 1; |
| | | |
| | | delayA = (int)totalDelay; |
| | | delayB = (int)totalDelay + 1; |
| | | |
| | | auto partial = totalDelay - delayA; |
| | | |
| | | gainA = 1 - partial; |
| | | gainB = partial; |
| | | } |
| | | }; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | |
| | | #pragma once |
| | | |
| | | //#include "ModulatedDelay.h" |
| | | #include "Utils.h" |
| | | #include <stdint.h> |
| | | #include <vector> |
| | | |
| | | namespace ReverbHallRoom |
| | | { |
| | | class ModulatedDelay |
| | | { |
| | | private: |
| | | |
| | | static const int ModulationUpdateRate = 8; |
| | | static const int DelayBufferSize = 192000 * 2; |
| | | |
| | | //float delayBuffer[DelayBufferSize] = { 0 }; |
| | | std::vector<float> delayBuffer; |
| | | int writeIndex; |
| | | int readIndexA; |
| | | int readIndexB; |
| | | uint64_t samplesProcessed; |
| | | |
| | | float modPhase; |
| | | float gainA; |
| | | float gainB; |
| | | |
| | | public: |
| | | int SampleDelay; |
| | | |
| | | float ModAmount; |
| | | float ModRate; |
| | | |
| | | ModulatedDelay() : delayBuffer(DelayBufferSize, 0) |
| | | { |
| | | writeIndex = 0; |
| | | readIndexA = 0; |
| | | readIndexB = 0; |
| | | samplesProcessed = 0; |
| | | |
| | | modPhase = 0.01 + 0.98 * (std::rand() / (float)RAND_MAX); |
| | | gainA = 0; |
| | | gainB = 0; |
| | | |
| | | SampleDelay = 100; |
| | | ModAmount = 0.0; |
| | | ModRate = 0.0; |
| | | |
| | | Update(); |
| | | } |
| | | |
| | | void Process(float* input, float* output, int bufSize) |
| | | { |
| | | for (int i = 0; i < bufSize; i++) |
| | | { |
| | | if (samplesProcessed >= ModulationUpdateRate) |
| | | { |
| | | Update(); |
| | | samplesProcessed = 0; |
| | | } |
| | | |
| | | delayBuffer[writeIndex] = input[i]; |
| | | output[i] = delayBuffer[readIndexA] * gainA + delayBuffer[readIndexB] * gainB; |
| | | |
| | | writeIndex++; |
| | | readIndexA++; |
| | | readIndexB++; |
| | | if (writeIndex >= DelayBufferSize) writeIndex -= DelayBufferSize; |
| | | if (readIndexA >= DelayBufferSize) readIndexA -= DelayBufferSize; |
| | | if (readIndexB >= DelayBufferSize) readIndexB -= DelayBufferSize; |
| | | samplesProcessed++; |
| | | } |
| | | } |
| | | |
| | | void ClearBuffers() |
| | | { |
| | | //Utils::ZeroBuffer(delayBuffer, DelayBufferSize); |
| | | Utils::ZeroBuffer(delayBuffer.data(), DelayBufferSize); |
| | | } |
| | | |
| | | |
| | | private: |
| | | void Update() |
| | | { |
| | | modPhase += ModRate * ModulationUpdateRate; |
| | | if (modPhase > 1) |
| | | modPhase = fmod(modPhase, 1.0); |
| | | |
| | | auto mod = sinf(modPhase * 2 * M_PI); |
| | | auto totalDelay = SampleDelay + ModAmount * mod; |
| | | |
| | | auto delayA = (int)totalDelay; |
| | | auto delayB = (int)totalDelay + 1; |
| | | |
| | | auto partial = totalDelay - delayA; |
| | | |
| | | gainA = 1 - partial; |
| | | gainB = partial; |
| | | |
| | | readIndexA = writeIndex - delayA; |
| | | readIndexB = writeIndex - delayB; |
| | | if (readIndexA < 0) readIndexA += DelayBufferSize; |
| | | if (readIndexB < 0) readIndexB += DelayBufferSize; |
| | | } |
| | | }; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | |
| | | #pragma once |
| | | |
| | | #include <vector> |
| | | #include <memory> |
| | | #include <array> |
| | | #include <cmath> |
| | | #include "Utils.h" |
| | | #include "RandomBuffer.h" |
| | | |
| | | namespace ReverbHallRoom |
| | | { |
| | | class MultitapDelay |
| | | { |
| | | public: |
| | | static const int MaxTaps = 256; |
| | | static const int DelayBufferSize = 192000 * 2; |
| | | |
| | | private: |
| | | //float delayBuffer[DelayBufferSize] = { 0 }; |
| | | std::vector<float> delayBuffer; |
| | | |
| | | float tapGains[MaxTaps] = { 0 }; |
| | | float tapPosition[MaxTaps] = { 0 }; |
| | | |
| | | std::vector<float> seedValues; |
| | | |
| | | int writeIdx; |
| | | int seed; |
| | | float crossSeed; |
| | | int count; |
| | | float lengthSamples; |
| | | float decay; |
| | | |
| | | public: |
| | | MultitapDelay() : delayBuffer(DelayBufferSize, 0) |
| | | { |
| | | writeIdx = 0; |
| | | seed = 0; |
| | | crossSeed = 0.0; |
| | | count = 1; |
| | | lengthSamples = 1000; |
| | | decay = 1.0; |
| | | |
| | | UpdateSeeds(); |
| | | } |
| | | |
| | | void SetSeed(int seed) |
| | | { |
| | | this->seed = seed; |
| | | UpdateSeeds(); |
| | | } |
| | | |
| | | void SetCrossSeed(float crossSeed) |
| | | { |
| | | this->crossSeed = crossSeed; |
| | | UpdateSeeds(); |
| | | } |
| | | |
| | | void SetTapCount(int tapCount) |
| | | { |
| | | if (tapCount < 1) tapCount = 1; |
| | | count = tapCount; |
| | | Update(); |
| | | } |
| | | |
| | | void SetTapLength(int tapLengthSamples) |
| | | { |
| | | if (tapLengthSamples < 10) tapLengthSamples = 10; |
| | | lengthSamples = tapLengthSamples; |
| | | Update(); |
| | | } |
| | | |
| | | void SetTapDecay(float tapDecay) |
| | | { |
| | | decay = tapDecay; |
| | | } |
| | | |
| | | void Process(float* input, float* output, int bufSize) |
| | | { |
| | | float lengthScaler = lengthSamples / (float)count; |
| | | float totalGain = 3.0 / std::sqrtf(1 + count); |
| | | totalGain *= (1 + decay * 2); |
| | | |
| | | for (int i = 0; i < bufSize; i++) |
| | | { |
| | | delayBuffer[writeIdx] = input[i]; |
| | | output[i] = 0; |
| | | |
| | | for (int j = 0; j < count; j++) |
| | | { |
| | | float offset = tapPosition[j] * lengthScaler; |
| | | float decayEffective = std::expf(-offset / lengthSamples * 3.3) * decay + (1-decay); |
| | | int readIdx = writeIdx - (int)offset; |
| | | if (readIdx < 0) readIdx += DelayBufferSize; |
| | | |
| | | output[i] += delayBuffer[readIdx] * tapGains[j] * decayEffective * totalGain; |
| | | } |
| | | |
| | | writeIdx = (writeIdx + 1) % DelayBufferSize; |
| | | } |
| | | } |
| | | |
| | | void ClearBuffers() |
| | | { |
| | | Utils::ZeroBuffer(delayBuffer.data(), DelayBufferSize); |
| | | } |
| | | |
| | | |
| | | private: |
| | | void Update() |
| | | { |
| | | int s = 0; |
| | | auto rand = [&]() {return seedValues[s++]; }; |
| | | |
| | | for (int i = 0; i < MaxTaps; i++) |
| | | { |
| | | float phase = rand() < 0.5 ? 1 : -1; |
| | | tapGains[i] = Utils::DB2Gainf(-20 + rand() * 20) * phase; |
| | | tapPosition[i] = i + rand(); |
| | | } |
| | | } |
| | | |
| | | void UpdateSeeds() |
| | | { |
| | | this->seedValues = RandomBuffer::Generate(seed, MaxTaps * 3, crossSeed); |
| | | Update(); |
| | | } |
| | | }; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | |
| | | #include "Parameters.h" |
| | | |
| | | namespace ReverbHallRoom |
| | | { |
| | | const char* ParameterLabel[Parameter::COUNT] = { |
| | | "Dry", |
| | | "Early", |
| | | "Late", |
| | | |
| | | "Interpolation", |
| | | "High_Cut_ON", |
| | | "Low_Cut_ON", |
| | | "Input Mix", |
| | | "High Cut", |
| | | "Low Cut", |
| | | "Cross Seed", |
| | | |
| | | "Multitap_Delay_ON", |
| | | "Count", |
| | | "Pre-delay", |
| | | "Decay", |
| | | "Length", |
| | | |
| | | "Early_Diffusion_ON", |
| | | "Diffusion Stages", |
| | | "Delay", |
| | | "Feedback", |
| | | "Mod Amt", |
| | | "Mod Rate", |
| | | |
| | | "Late_Mode", |
| | | "Late_Diffusion_ON", |
| | | "Line_Count", |
| | | "Line_Size", |
| | | "Line_Mod_Amt", |
| | | "Line_Decay", |
| | | "Line_Mod_Rate", |
| | | "Diffusion Stages", |
| | | "Diffusion_Delay", |
| | | "Diffusion_Feedback", |
| | | "Diffusion_Mod Amt", |
| | | "Diffusion_Mod Rate", |
| | | |
| | | "EQ_Low_Shelf_ON", |
| | | "EQ_High_Shelf_ON", |
| | | "EQ_Lowpass_ON", |
| | | "Low_Freq", |
| | | "Low Gain", |
| | | "High Freq", |
| | | "High Gain", |
| | | "LP_Cutoff_Freq", |
| | | |
| | | "Tap Seed", |
| | | "Diffusion Seed", |
| | | "Delay Seed", |
| | | "Late Diffusion Seed", |
| | | /* |
| | | "Interpolation", |
| | | "High Cut", |
| | | "Low Cut", |
| | | "Input Mix", |
| | | "High Cut", |
| | | "Low Cut", |
| | | "Dry", |
| | | "Early", |
| | | "Late", |
| | | |
| | | "Multitap Delay", |
| | | "Count", |
| | | "Decay", |
| | | "Pre-delay", |
| | | "Length", |
| | | |
| | | "Diffusion", |
| | | "Diffusion Stages", |
| | | "Delay", |
| | | "Mod Amt", |
| | | "Feedback", |
| | | "Mod Rate", |
| | | |
| | | "Mode", |
| | | "Line Count", |
| | | "Diffusion", |
| | | "Diffusion Stages", |
| | | "Size", |
| | | "Mod Amt", |
| | | "Delay", |
| | | "Mod Amt", |
| | | "Decay", |
| | | "Mod Rate", |
| | | "Feedback", |
| | | "Mod Rate", |
| | | |
| | | "Low Shelf", |
| | | "High Shelf", |
| | | "Lowpass", |
| | | "Low Freq", |
| | | "High Freq", |
| | | "Cutoff", |
| | | "Low Gain", |
| | | "High Gain", |
| | | "Cross Seed", |
| | | |
| | | "Tap Seed", |
| | | "Diffusion Seed", |
| | | "Delay Seed", |
| | | "Late Diffusion Seed", |
| | | */ |
| | | }; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | |
| | | #pragma once |
| | | |
| | | #include <math.h> |
| | | #include <stdio.h> |
| | | #include <string.h> |
| | | #include "Utils.h" |
| | | #include <stdio.h> |
| | | |
| | | |
| | | |
| | | #ifndef MAX_STR_SIZE |
| | | #define MAX_STR_SIZE 64 |
| | | #endif |
| | | |
| | | |
| | | namespace ReverbHallRoom |
| | | { |
| | | namespace Parameter |
| | | { |
| | | const int DryOut = 0; |
| | | const int EarlyOut = 1; |
| | | const int LateOut = 2; |
| | | |
| | | const int Interpolation = 3; |
| | | const int HighCutEnabled = 4; |
| | | const int LowCutEnabled = 5; |
| | | const int InputMix = 6; |
| | | const int HighCut = 7; |
| | | const int LowCut = 8; |
| | | const int EqCrossSeed = 9; |
| | | |
| | | const int TapEnabled = 10; |
| | | const int TapCount = 11; |
| | | const int TapPredelay = 12; |
| | | const int TapDecay = 13; |
| | | const int TapLength = 14; |
| | | |
| | | const int EarlyDiffuseEnabled = 15; |
| | | const int EarlyDiffuseCount = 16; |
| | | const int EarlyDiffuseDelay = 17; |
| | | const int EarlyDiffuseFeedback = 18; |
| | | const int EarlyDiffuseModAmount = 19; |
| | | const int EarlyDiffuseModRate = 20; |
| | | |
| | | const int LateMode = 21; |
| | | const int LateDiffuseEnabled = 22; |
| | | const int LateLineCount = 23; |
| | | const int LateLineSize = 24; |
| | | const int LateLineModAmount = 25; |
| | | const int LateLineDecay = 26; |
| | | const int LateLineModRate = 27; |
| | | const int LateDiffuseCount = 28; |
| | | const int LateDiffuseDelay = 29; |
| | | const int LateDiffuseFeedback = 30; |
| | | const int LateDiffuseModAmount = 31; |
| | | const int LateDiffuseModRate = 32; |
| | | |
| | | const int EqLowShelfEnabled = 33; |
| | | const int EqHighShelfEnabled = 34; |
| | | const int EqLowpassEnabled = 35; |
| | | const int EqLowFreq = 36; |
| | | const int EqLowGain = 37; |
| | | const int EqHighFreq = 38; |
| | | const int EqHighGain = 39; |
| | | const int EqCutoff = 40; |
| | | |
| | | const int SeedTap = 41; |
| | | const int SeedDiffusion = 42; |
| | | const int SeedDelay = 43; |
| | | const int SeedPostDiffusion = 44; |
| | | |
| | | const int COUNT = 45; |
| | | /* |
| | | const int Interpolation = 0; |
| | | const int LowCutEnabled = 1; |
| | | const int HighCutEnabled = 2; |
| | | const int InputMix = 3; |
| | | const int LowCut = 4; |
| | | const int HighCut = 5; |
| | | const int DryOut = 6; |
| | | const int EarlyOut = 7; |
| | | const int LateOut = 8; |
| | | |
| | | const int TapEnabled = 9; |
| | | const int TapCount = 10; |
| | | const int TapDecay = 11; |
| | | const int TapPredelay = 12; |
| | | const int TapLength = 13; |
| | | |
| | | const int EarlyDiffuseEnabled = 14; |
| | | const int EarlyDiffuseCount = 15; |
| | | const int EarlyDiffuseDelay = 16; |
| | | const int EarlyDiffuseModAmount = 17; |
| | | const int EarlyDiffuseFeedback = 18; |
| | | const int EarlyDiffuseModRate = 19; |
| | | |
| | | const int LateMode = 20; |
| | | const int LateLineCount = 21; |
| | | const int LateDiffuseEnabled = 22; |
| | | const int LateDiffuseCount = 23; |
| | | const int LateLineSize = 24; |
| | | const int LateLineModAmount = 25; |
| | | const int LateDiffuseDelay = 26; |
| | | const int LateDiffuseModAmount = 27; |
| | | const int LateLineDecay = 28; |
| | | const int LateLineModRate = 29; |
| | | const int LateDiffuseFeedback = 30; |
| | | const int LateDiffuseModRate = 31; |
| | | |
| | | const int EqLowShelfEnabled = 32; |
| | | const int EqHighShelfEnabled = 33; |
| | | const int EqLowpassEnabled = 34; |
| | | const int EqLowFreq = 35; |
| | | const int EqHighFreq = 36; |
| | | const int EqCutoff = 37; |
| | | const int EqLowGain = 38; |
| | | const int EqHighGain = 39; |
| | | const int EqCrossSeed = 40; |
| | | |
| | | const int SeedTap = 41; |
| | | const int SeedDiffusion = 42; |
| | | const int SeedDelay = 43; |
| | | const int SeedPostDiffusion = 44; |
| | | |
| | | const int COUNT = 45; |
| | | */ |
| | | }; |
| | | |
| | | extern const char* ParameterLabel[Parameter::COUNT]; |
| | | |
| | | inline double ScaleParam(double val, int index) |
| | | { |
| | | switch (index) |
| | | { |
| | | case Parameter::Interpolation: |
| | | case Parameter::LowCutEnabled: |
| | | case Parameter::HighCutEnabled: |
| | | case Parameter::TapEnabled: |
| | | case Parameter::LateDiffuseEnabled: |
| | | case Parameter::EqLowShelfEnabled: |
| | | case Parameter::EqHighShelfEnabled: |
| | | case Parameter::EqLowpassEnabled: |
| | | case Parameter::EarlyDiffuseEnabled: |
| | | return val < 0.5 ? 0.0 : 1.0; |
| | | |
| | | case Parameter::InputMix: |
| | | case Parameter::EarlyDiffuseFeedback: |
| | | case Parameter::TapDecay: |
| | | case Parameter::LateDiffuseFeedback: |
| | | case Parameter::EqCrossSeed: |
| | | return val; |
| | | |
| | | case Parameter::SeedTap: |
| | | case Parameter::SeedDiffusion: |
| | | case Parameter::SeedDelay: |
| | | case Parameter::SeedPostDiffusion: |
| | | return (int)floor(val * 999.999); |
| | | |
| | | case Parameter::LowCut: |
| | | return 20 + Utils::Resp4oct(val) * 980; |
| | | case Parameter::HighCut: |
| | | return 400 + Utils::Resp4oct(val) * 19600; |
| | | |
| | | case Parameter::DryOut: |
| | | case Parameter::EarlyOut: |
| | | case Parameter::LateOut: |
| | | return -30 + val * 30; |
| | | |
| | | case Parameter::TapCount: |
| | | return (int)(1 + val * 255); |
| | | case Parameter::TapPredelay: |
| | | return Utils::Resp1dec(val) * 500; |
| | | case Parameter::TapLength: |
| | | return 10 + val * 990; |
| | | |
| | | case Parameter::EarlyDiffuseCount: |
| | | return (int)(1 + val * 11.999); |
| | | case Parameter::EarlyDiffuseDelay: |
| | | return 10 + val * 90; |
| | | case Parameter::EarlyDiffuseModAmount: |
| | | return val * 2.5; |
| | | case Parameter::EarlyDiffuseModRate: |
| | | return Utils::Resp2dec(val) * 5; |
| | | |
| | | case Parameter::LateMode: |
| | | return val < 0.5 ? 0.0 : 1.0; |
| | | case Parameter::LateLineCount: |
| | | return (int)(1 + val * 11.999); |
| | | case Parameter::LateDiffuseCount: |
| | | return (int)(1 + val * 7.999); |
| | | case Parameter::LateLineSize: |
| | | return 20 + Utils::Resp2dec(val) * 980; |
| | | case Parameter::LateLineModAmount: |
| | | return val * 2.5; |
| | | case Parameter::LateDiffuseDelay: |
| | | return 10 + val * 90; |
| | | case Parameter::LateDiffuseModAmount: |
| | | return val * 2.5; |
| | | case Parameter::LateLineDecay: |
| | | return 0.05 + Utils::Resp3dec(val) * 59.95; |
| | | case Parameter::LateLineModRate: |
| | | return Utils::Resp2dec(val) * 5; |
| | | case Parameter::LateDiffuseModRate: |
| | | return Utils::Resp2dec(val) * 5; |
| | | |
| | | case Parameter::EqLowFreq: |
| | | return 20 + Utils::Resp3oct(val) * 980; |
| | | case Parameter::EqHighFreq: |
| | | return 400 + Utils::Resp4oct(val) * 19600; |
| | | case Parameter::EqCutoff: |
| | | return 400 + Utils::Resp4oct(val) * 19600; |
| | | case Parameter::EqLowGain: |
| | | return -20 + val * 20; |
| | | case Parameter::EqHighGain: |
| | | return -20 + val * 20; |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | inline void FormatParameter(double val, int maxLen, int paramId, char* buffer) |
| | | { |
| | | double s = ScaleParam(val, paramId); |
| | | |
| | | switch (paramId) |
| | | { |
| | | case Parameter::Interpolation: |
| | | case Parameter::HighCutEnabled: |
| | | case Parameter::LowCutEnabled: |
| | | case Parameter::TapEnabled: |
| | | case Parameter::LateDiffuseEnabled: |
| | | case Parameter::EqLowShelfEnabled: |
| | | case Parameter::EqHighShelfEnabled: |
| | | case Parameter::EqLowpassEnabled: |
| | | case Parameter::EarlyDiffuseEnabled: |
| | | if (ScaleParam(val, paramId) == 1) |
| | | strcpy_s(buffer, MAX_STR_SIZE, "ENABLED"); |
| | | else |
| | | strcpy_s(buffer, MAX_STR_SIZE, "DISABLED"); |
| | | break; |
| | | |
| | | case Parameter::InputMix: |
| | | case Parameter::EarlyDiffuseFeedback: |
| | | case Parameter::TapDecay: |
| | | case Parameter::LateDiffuseFeedback: |
| | | case Parameter::EqCrossSeed: |
| | | snprintf(buffer, MAX_STR_SIZE, "%d%%", (int)(s * 100)); |
| | | break; |
| | | |
| | | case Parameter::SeedTap: |
| | | case Parameter::SeedDiffusion: |
| | | case Parameter::SeedDelay: |
| | | case Parameter::SeedPostDiffusion: |
| | | snprintf(buffer, MAX_STR_SIZE, "%03d", (int)s); |
| | | break; |
| | | |
| | | case Parameter::LowCut: |
| | | case Parameter::HighCut: |
| | | case Parameter::EqLowFreq: |
| | | case Parameter::EqHighFreq: |
| | | case Parameter::EqCutoff: |
| | | snprintf(buffer, MAX_STR_SIZE, "%d Hz", (int)s); |
| | | break; |
| | | |
| | | case Parameter::DryOut: |
| | | case Parameter::EarlyOut: |
| | | case Parameter::LateOut: |
| | | if (s <= -30) |
| | | strcpy_s(buffer, MAX_STR_SIZE, "MUTED"); |
| | | else |
| | | snprintf(buffer, MAX_STR_SIZE, "%.1f dB", s); |
| | | break; |
| | | |
| | | case Parameter::TapCount: |
| | | case Parameter::EarlyDiffuseCount: |
| | | case Parameter::LateLineCount: |
| | | case Parameter::LateDiffuseCount: |
| | | snprintf(buffer, MAX_STR_SIZE, "%d", (int)s); |
| | | break; |
| | | |
| | | case Parameter::TapPredelay: |
| | | case Parameter::TapLength: |
| | | case Parameter::EarlyDiffuseDelay: |
| | | case Parameter::LateLineSize: |
| | | case Parameter::LateDiffuseDelay: |
| | | snprintf(buffer, MAX_STR_SIZE, "%d ms", (int)s); |
| | | break; |
| | | |
| | | case Parameter::LateLineDecay: |
| | | if (s < 1) |
| | | snprintf(buffer, MAX_STR_SIZE, "%d ms", (int)(s * 1000)); |
| | | else if (s < 10) |
| | | snprintf(buffer, MAX_STR_SIZE, "%.2f sec", s); |
| | | else |
| | | snprintf(buffer, MAX_STR_SIZE, "%.1f sec", s); |
| | | break; |
| | | |
| | | case Parameter::LateMode: |
| | | if (s == 1) |
| | | strcpy_s(buffer, MAX_STR_SIZE, "POST"); |
| | | else |
| | | strcpy_s(buffer, MAX_STR_SIZE, "PRE"); |
| | | break; |
| | | |
| | | case Parameter::EarlyDiffuseModAmount: |
| | | case Parameter::LateLineModAmount: |
| | | case Parameter::LateDiffuseModAmount: |
| | | snprintf(buffer, MAX_STR_SIZE, "%d%%", (int)(s * 100)); |
| | | break; |
| | | |
| | | case Parameter::EarlyDiffuseModRate: |
| | | case Parameter::LateLineModRate: |
| | | case Parameter::LateDiffuseModRate: |
| | | snprintf(buffer, MAX_STR_SIZE, "%.2f Hz", s); |
| | | break; |
| | | |
| | | case Parameter::EqLowGain: |
| | | case Parameter::EqHighGain: |
| | | snprintf(buffer, MAX_STR_SIZE, "%.1f dB", s); |
| | | break; |
| | | |
| | | default: |
| | | snprintf(buffer, MAX_STR_SIZE, "%.2f", s); |
| | | } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | |
| | | #pragma once |
| | | |
| | | #include "Parameters.h" |
| | | |
| | | namespace ReverbHallRoom |
| | | { |
| | | float ProgramDarkPlate[Parameter::COUNT]; |
| | | #if 1 |
| | | void initPrograms(Reverb_common *common, Reverb_taps *taps, Reverb_early *early, Reverb_late *late, Reverb_eq *eq) |
| | | { |
| | | ProgramDarkPlate[Parameter::DryOut] = common->dry; //0.6f; // 干声æ¯ä¾éä¸ |
| | | ProgramDarkPlate[Parameter::EarlyOut] = common->early; //0.7f; // æ©æåå°è¾åºå¢ç |
| | | ProgramDarkPlate[Parameter::LateOut] = common->late; //0.8f; // åææ··åè¾åºå¢ç |
| | | ProgramDarkPlate[Parameter::Interpolation] = common->input_mix_on; //1.0f; // å¯ç¨æå¼ |
| | | ProgramDarkPlate[Parameter::HighCutEnabled] = common->high_cut_on; //1.0f; // å¯ç¨é«å |
| | | ProgramDarkPlate[Parameter::LowCutEnabled] = common->low_cut_on; //1.0f; // å¯ç¨ä½å |
| | | ProgramDarkPlate[Parameter::InputMix] = common->input_mix; //0.25f; // è¾å
¥äº¤å 25% |
| | | ProgramDarkPlate[Parameter::HighCut] = common->high_cut; //0.8f; // é«å约 16kHz |
| | | ProgramDarkPlate[Parameter::LowCut] = common->low_cut; //0.4f; // ä½å约 400Hz |
| | | ProgramDarkPlate[Parameter::EqCrossSeed] = common->cross_seed; //0.5f; // å·¦å³åè¡¡ä¸çç¸å
³æ§ |
| | | |
| | | ProgramDarkPlate[Parameter::TapEnabled] = taps->multi_taps_on; //1.0f; // å¯ç¨æ©æåå° |
| | | ProgramDarkPlate[Parameter::TapCount] = taps->taps_count; //0.7f; // æ½å¤´æ°çº¦ 180 |
| | | ProgramDarkPlate[Parameter::TapPredelay] = taps->taps_delay; //0.4f; // é¢å»¶è¿ 200ms |
| | | ProgramDarkPlate[Parameter::TapDecay] = taps->taps_decay; //0.7f; // æ©æåå°è¡°å |
| | | ProgramDarkPlate[Parameter::TapLength] = taps->taps_length; //0.8f; // æ©æåå°é¿åº¦ 800ms |
| | | |
| | | ProgramDarkPlate[Parameter::EarlyDiffuseEnabled] = early->early_difus_on; //1.0f; // å¯ç¨æ©ææ©æ£å¨ |
| | | ProgramDarkPlate[Parameter::EarlyDiffuseCount] = early->early_count; //0.4f; // æ©ææ©æ£çº§æ° 5 çº§å·¦å³ |
| | | ProgramDarkPlate[Parameter::EarlyDiffuseDelay] = early->early_delay; //0.3f; // 约 37ms |
| | | ProgramDarkPlate[Parameter::EarlyDiffuseFeedback] = early->early_feedback; //0.6f; // åé¦ 0.6 |
| | | ProgramDarkPlate[Parameter::EarlyDiffuseModAmount] = early->early_mod_amt; //0.15f; // 轻微è°å¶ |
| | | ProgramDarkPlate[Parameter::EarlyDiffuseModRate] = early->early_mod_rate; //0.2f; // 约 1Hz |
| | | |
| | | ProgramDarkPlate[Parameter::LateMode] = late->late_mode; //1.0f; // POST 模å¼ï¼åå
鍿©æ£å |
| | | // ProgramDarkPlate[Parameter::LateDiffuseEnabled] = 0.5f;//late->late_reflect_on; //1.0f; // å¯ç¨åææ©æ£ |
| | | ProgramDarkPlate[Parameter::LateDiffuseEnabled] = late->late_reflect_on; //1.0f; // å¯ç¨åææ©æ£ |
| | | ProgramDarkPlate[Parameter::LateLineCount] = late->line_count; //0.9f; // 11 æ¡å»¶è¿çº¿ |
| | | ProgramDarkPlate[Parameter::LateLineSize] = late->line_size; //0.7f; // å»¶è¿çº¿é¿åº¦çº¦ 700ms |
| | | ProgramDarkPlate[Parameter::LateLineModAmount] = late->line_mod_amt; //0.3f; // è°å¶æ·±åº¦çº¦ 0.75ms |
| | | ProgramDarkPlate[Parameter::LateLineDecay] = late->line_decay; //0.25f; // æ··åæ¶é´çº¦ 2 ç§ï¼å¬è§è°æ´ï¼ |
| | | ProgramDarkPlate[Parameter::LateLineModRate] = late->line_mod_rate; //0.25f; // è°å¶éç约 1.25Hz |
| | | ProgramDarkPlate[Parameter::LateDiffuseCount] = late->difus_count; //0.6f; // åææ©æ£çº§æ° 5 级 |
| | | // ProgramDarkPlate[Parameter::LateDiffuseDelay] = late->difus_delay; //0.3f; // 约 37ms |
| | | ProgramDarkPlate[Parameter::LateDiffuseDelay] = late->difus_delay; |
| | | ProgramDarkPlate[Parameter::LateDiffuseFeedback] = late->difus_feedback; //0.7f; // åé¦ 0.7 |
| | | ProgramDarkPlate[Parameter::LateDiffuseModAmount] = late->difus_mod_amt; //0.15f; // 轻微è°å¶ |
| | | ProgramDarkPlate[Parameter::LateDiffuseModRate] = late->difus_mod_rate; //0.2f; // 约 1Hz |
| | | |
| | | ProgramDarkPlate[Parameter::EqLowShelfEnabled] = eq->low_shelf_on; //0.0f; // ç¦ç¨ä½æ¶ |
| | | ProgramDarkPlate[Parameter::EqHighShelfEnabled] = eq->high_shelf_on; //1.0f; // å¯ç¨é«æ¶ |
| | | ProgramDarkPlate[Parameter::EqLowpassEnabled] = eq->low_pass_on; //1.0f; // å¯ç¨ä½é |
| | | ProgramDarkPlate[Parameter::EqLowFreq] = eq->low_shelf_freq; //0.4f; // 使¶è½¬æ 400Hz |
| | | ProgramDarkPlate[Parameter::EqLowGain] = eq->low_shelf_gain; //0.5f; // 使¶å¢ç 0dB éè¿ |
| | | ProgramDarkPlate[Parameter::EqHighFreq] = eq->high_shelf_freq; //0.6f; // 髿¶è½¬æ 10kHz |
| | | ProgramDarkPlate[Parameter::EqHighGain] = eq->high_shelf_gain; //0.7f; // 髿¶å¢ç +8dB |
| | | ProgramDarkPlate[Parameter::EqCutoff] = eq->low_pass_freq; //0.7f; // ä½éæªæ¢çº¦ 14kHz |
| | | |
| | | ProgramDarkPlate[Parameter::SeedDelay] = 0.5f; // éæºç§å |
| | | ProgramDarkPlate[Parameter::SeedDiffusion] = 0.5f; |
| | | ProgramDarkPlate[Parameter::SeedPostDiffusion] = 0.5f; |
| | | ProgramDarkPlate[Parameter::SeedTap] = 0.5f; |
| | | |
| | | } |
| | | #else |
| | | void initPrograms() |
| | | { |
| | | ProgramDarkPlate[Parameter::DryOut] = 0.8705999851226807; |
| | | ProgramDarkPlate[Parameter::EarlyDiffuseCount] = 0.2960000038146973; |
| | | ProgramDarkPlate[Parameter::EarlyDiffuseDelay] = 0.3066999912261963; |
| | | ProgramDarkPlate[Parameter::EarlyDiffuseEnabled] = 0.0; |
| | | ProgramDarkPlate[Parameter::EarlyDiffuseFeedback] = 0.7706999778747559; |
| | | ProgramDarkPlate[Parameter::EarlyDiffuseModAmount] = 0.143899992108345; |
| | | ProgramDarkPlate[Parameter::EarlyDiffuseModRate] = 0.2466999888420105; |
| | | ProgramDarkPlate[Parameter::EarlyOut] = 0.3; //0.0 |
| | | ProgramDarkPlate[Parameter::EqCrossSeed] = 0.0; |
| | | ProgramDarkPlate[Parameter::EqCutoff] = 0.9759999513626099; |
| | | ProgramDarkPlate[Parameter::EqHighFreq] = 0.5133999586105347; |
| | | ProgramDarkPlate[Parameter::EqHighGain] = 0.7680000066757202; |
| | | ProgramDarkPlate[Parameter::EqHighShelfEnabled] = 1.0; |
| | | ProgramDarkPlate[Parameter::EqLowFreq] = 0.3879999816417694; |
| | | ProgramDarkPlate[Parameter::EqLowGain] = 0.5559999942779541; |
| | | ProgramDarkPlate[Parameter::EqLowShelfEnabled] = 0.0; |
| | | ProgramDarkPlate[Parameter::EqLowpassEnabled] = 0.0; |
| | | ProgramDarkPlate[Parameter::HighCut] = 0.2933000028133392; |
| | | ProgramDarkPlate[Parameter::HighCutEnabled] = 0.0; |
| | | ProgramDarkPlate[Parameter::InputMix] = 0.2346999943256378; |
| | | ProgramDarkPlate[Parameter::Interpolation] = 1.0; |
| | | ProgramDarkPlate[Parameter::LateDiffuseCount] = 0.4879999756813049; |
| | | ProgramDarkPlate[Parameter::LateDiffuseDelay] = 0.239999994635582; |
| | | ProgramDarkPlate[Parameter::LateDiffuseEnabled] = 1.0; |
| | | ProgramDarkPlate[Parameter::LateDiffuseFeedback] = 0.8506999611854553; |
| | | ProgramDarkPlate[Parameter::LateDiffuseModAmount] = 0.1467999964952469; |
| | | ProgramDarkPlate[Parameter::LateDiffuseModRate] = 0.1666999906301498; |
| | | ProgramDarkPlate[Parameter::LateLineCount] = 1.0; |
| | | ProgramDarkPlate[Parameter::LateLineDecay] = 0.6345999836921692; |
| | | ProgramDarkPlate[Parameter::LateLineModAmount] = 0.2719999849796295; |
| | | ProgramDarkPlate[Parameter::LateLineModRate] = 0.2292999923229218; |
| | | ProgramDarkPlate[Parameter::LateLineSize] = 0.4693999886512756; |
| | | ProgramDarkPlate[Parameter::LateMode] = 1.0; |
| | | ProgramDarkPlate[Parameter::LateOut] = 0.6613999605178833; |
| | | ProgramDarkPlate[Parameter::LowCut] = 0.6399999856948853; |
| | | ProgramDarkPlate[Parameter::LowCutEnabled] = 1.0; |
| | | ProgramDarkPlate[Parameter::SeedDelay] = 0.2180999964475632; |
| | | ProgramDarkPlate[Parameter::SeedDiffusion] = 0.1850000023841858; |
| | | ProgramDarkPlate[Parameter::SeedPostDiffusion] = 0.3652999997138977; |
| | | ProgramDarkPlate[Parameter::SeedTap] = 0.3339999914169312; |
| | | ProgramDarkPlate[Parameter::TapDecay] = 1.0; |
| | | ProgramDarkPlate[Parameter::TapLength] = 0.9866999983787537; |
| | | ProgramDarkPlate[Parameter::TapPredelay] = 0.0; |
| | | ProgramDarkPlate[Parameter::TapCount] = 0.1959999948740005; |
| | | ProgramDarkPlate[Parameter::TapEnabled] = 0.0; |
| | | } |
| | | #endif |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | |
| | | #include <climits> |
| | | #include "RandomBuffer.h" |
| | | #include "LcgRandom.h" |
| | | |
| | | namespace ReverbHallRoom |
| | | { |
| | | std::vector<float> RandomBuffer::Generate(uint64_t seed, int count) |
| | | { |
| | | LcgRandom rand(seed); |
| | | std::vector<float> output; |
| | | |
| | | for (int i = 0; i < count; i++) |
| | | { |
| | | unsigned int val = rand.NextUInt(); |
| | | float fVal = val / (float)UINT_MAX; |
| | | output.push_back(fVal); |
| | | } |
| | | |
| | | return output; |
| | | } |
| | | |
| | | std::vector<float> RandomBuffer::Generate(uint64_t seed, int count, float crossSeed) |
| | | { |
| | | auto seedA = seed; |
| | | auto seedB = ~seed; |
| | | auto seriesA = Generate(seedA, count); |
| | | auto seriesB = Generate(seedB, count); |
| | | |
| | | std::vector<float> output; |
| | | for (int i = 0; i < count; i++) |
| | | output.push_back(seriesA[i] * (1 - crossSeed) + seriesB[i] * crossSeed); |
| | | |
| | | return output; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | |
| | | #pragma once |
| | | |
| | | #include <vector> |
| | | #include <stdint.h> |
| | | |
| | | namespace ReverbHallRoom |
| | | { |
| | | class RandomBuffer |
| | | { |
| | | public: |
| | | static std::vector<float> Generate(uint64_t seed, int count); |
| | | static std::vector<float> Generate(uint64_t seed, int count, float crossSeed); |
| | | }; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | |
| | | #pragma once |
| | | |
| | | #include <map> |
| | | #include <memory> |
| | | #include "Parameters.h" |
| | | #include "ModulatedDelay.h" |
| | | #include "MultitapDelay.h" |
| | | #include "RandomBuffer.h" |
| | | #include "Lp1.h" |
| | | #include "Hp1.h" |
| | | #include "DelayLine.h" |
| | | #include "AllpassDiffuser.h" |
| | | #include <cmath> |
| | | #include "ReverbChannel.h" |
| | | #include "Utils.h" |
| | | |
| | | namespace ReverbHallRoom |
| | | { |
| | | enum class ChannelLR |
| | | { |
| | | Left, |
| | | Right |
| | | }; |
| | | |
| | | class ReverbChannel |
| | | { |
| | | private: |
| | | static const int TotalLineCount = 12; |
| | | |
| | | double paramsScaled[Parameter::COUNT] = { 0.0 }; |
| | | int samplerate; |
| | | |
| | | ModulatedDelay preDelay; |
| | | MultitapDelay multitap; |
| | | AllpassDiffuser diffuser; |
| | | DelayLine lines[TotalLineCount]; |
| | | RandomBuffer rand; |
| | | Hp1 highPass; |
| | | Lp1 lowPass; |
| | | |
| | | int delayLineSeed; |
| | | int postDiffusionSeed; |
| | | |
| | | // Used the the main process loop |
| | | int lineCount; |
| | | |
| | | bool lowCutEnabled; |
| | | bool highCutEnabled; |
| | | bool multitapEnabled; |
| | | bool diffuserEnabled; |
| | | float inputMix; |
| | | float dryOut; |
| | | float earlyOut; |
| | | float lineOut; |
| | | float crossSeed; |
| | | ChannelLR channelLr; |
| | | |
| | | public: |
| | | |
| | | ReverbChannel(int samplerate, ChannelLR leftOrRight) |
| | | { |
| | | this->channelLr = leftOrRight; |
| | | crossSeed = 0.0; |
| | | lineCount = 8; |
| | | diffuser.SetInterpolationEnabled(true); |
| | | highPass.SetCutoffHz(20); |
| | | lowPass.SetCutoffHz(20000); |
| | | SetSamplerate(samplerate); |
| | | } |
| | | |
| | | int GetSamplerate() |
| | | { |
| | | return samplerate; |
| | | } |
| | | |
| | | void SetSamplerate(int samplerate) |
| | | { |
| | | this->samplerate = samplerate; |
| | | highPass.SetSamplerate(samplerate); |
| | | lowPass.SetSamplerate(samplerate); |
| | | diffuser.SetSamplerate(samplerate); |
| | | |
| | | for (int i = 0; i < TotalLineCount; i++) |
| | | lines[i].SetSamplerate(samplerate); |
| | | |
| | | ReapplyAllParams(); |
| | | ClearBuffers(); |
| | | UpdateLines(); |
| | | } |
| | | |
| | | void ReapplyAllParams() |
| | | { |
| | | for (int i = 0; i < Parameter::COUNT; i++) |
| | | SetParameter(i, paramsScaled[i]); |
| | | } |
| | | |
| | | void SetParameter(int para, double scaledValue) |
| | | { |
| | | paramsScaled[para] = scaledValue; |
| | | |
| | | switch (para) |
| | | { |
| | | case Parameter::Interpolation: |
| | | for (int i = 0; i < TotalLineCount; i++) |
| | | lines[i].SetInterpolationEnabled(scaledValue >= 0.5); |
| | | break; |
| | | case Parameter::LowCutEnabled: |
| | | lowCutEnabled = scaledValue >= 0.5; |
| | | if (lowCutEnabled) |
| | | highPass.ClearBuffers(); |
| | | break; |
| | | case Parameter::HighCutEnabled: |
| | | highCutEnabled = scaledValue >= 0.5; |
| | | if (highCutEnabled) |
| | | lowPass.ClearBuffers(); |
| | | break; |
| | | case Parameter::InputMix: |
| | | inputMix = scaledValue; |
| | | break; |
| | | case Parameter::LowCut: |
| | | highPass.SetCutoffHz(scaledValue); |
| | | break; |
| | | case Parameter::HighCut: |
| | | lowPass.SetCutoffHz(scaledValue); |
| | | break; |
| | | case Parameter::DryOut: |
| | | dryOut = scaledValue <= -30 ? 0.0 : Utils::DB2Gainf(scaledValue); |
| | | break; |
| | | case Parameter::EarlyOut: |
| | | earlyOut = scaledValue <= -30 ? 0.0 : Utils::DB2Gainf(scaledValue); |
| | | break; |
| | | case Parameter::LateOut: |
| | | lineOut = scaledValue <= -30 ? 0.0 : Utils::DB2Gainf(scaledValue); |
| | | break; |
| | | |
| | | |
| | | case Parameter::TapEnabled: |
| | | { |
| | | auto newVal = scaledValue >= 0.5; |
| | | if (newVal != multitapEnabled) |
| | | multitap.ClearBuffers(); |
| | | multitapEnabled = newVal; |
| | | break; |
| | | } |
| | | case Parameter::TapCount: |
| | | multitap.SetTapCount((int)scaledValue); |
| | | break; |
| | | case Parameter::TapDecay: |
| | | multitap.SetTapDecay(scaledValue); |
| | | break; |
| | | case Parameter::TapPredelay: |
| | | preDelay.SampleDelay = (int)Ms2Samples(scaledValue); |
| | | break; |
| | | case Parameter::TapLength: |
| | | multitap.SetTapLength((int)Ms2Samples(scaledValue)); |
| | | break; |
| | | |
| | | |
| | | case Parameter::EarlyDiffuseEnabled: |
| | | { |
| | | auto newVal = scaledValue >= 0.5; |
| | | if (newVal != diffuserEnabled) |
| | | diffuser.ClearBuffers(); |
| | | diffuserEnabled = newVal; |
| | | break; |
| | | } |
| | | case Parameter::EarlyDiffuseCount: |
| | | diffuser.Stages = (int)scaledValue; |
| | | break; |
| | | case Parameter::EarlyDiffuseDelay: |
| | | diffuser.SetDelay((int)Ms2Samples(scaledValue)); |
| | | break; |
| | | case Parameter::EarlyDiffuseModAmount: |
| | | diffuser.SetModulationEnabled(scaledValue > 0.5); |
| | | diffuser.SetModAmount(Ms2Samples(scaledValue)); |
| | | break; |
| | | case Parameter::EarlyDiffuseFeedback: |
| | | diffuser.SetFeedback(scaledValue); |
| | | break; |
| | | case Parameter::EarlyDiffuseModRate: |
| | | diffuser.SetModRate(scaledValue); |
| | | break; |
| | | |
| | | |
| | | case Parameter::LateMode: |
| | | for (int i = 0; i < TotalLineCount; i++) |
| | | lines[i].TapPostDiffuser = scaledValue >= 0.5; |
| | | break; |
| | | case Parameter::LateLineCount: |
| | | lineCount = (int)scaledValue; |
| | | break; |
| | | case Parameter::LateDiffuseEnabled: |
| | | for (int i = 0; i < TotalLineCount; i++) |
| | | { |
| | | auto newVal = scaledValue >= 0.5; |
| | | if (newVal != lines[i].DiffuserEnabled) |
| | | lines[i].ClearDiffuserBuffer(); |
| | | lines[i].DiffuserEnabled = newVal; |
| | | } |
| | | break; |
| | | case Parameter::LateDiffuseCount: |
| | | for (int i = 0; i < TotalLineCount; i++) |
| | | lines[i].SetDiffuserStages((int)scaledValue); |
| | | break; |
| | | case Parameter::LateLineSize: |
| | | UpdateLines(); |
| | | break; |
| | | case Parameter::LateLineModAmount: |
| | | UpdateLines(); |
| | | break; |
| | | case Parameter::LateDiffuseDelay: |
| | | for (int i = 0; i < TotalLineCount; i++) |
| | | lines[i].SetDiffuserDelay((int)Ms2Samples(scaledValue)); |
| | | break; |
| | | case Parameter::LateDiffuseModAmount: |
| | | UpdateLines(); |
| | | break; |
| | | case Parameter::LateLineDecay: |
| | | UpdateLines(); |
| | | break; |
| | | case Parameter::LateLineModRate: |
| | | UpdateLines(); |
| | | break; |
| | | case Parameter::LateDiffuseFeedback: |
| | | for (int i = 0; i < TotalLineCount; i++) |
| | | lines[i].SetDiffuserFeedback(scaledValue); |
| | | break; |
| | | case Parameter::LateDiffuseModRate: |
| | | UpdateLines(); |
| | | break; |
| | | |
| | | |
| | | case Parameter::EqLowShelfEnabled: |
| | | for (int i = 0; i < TotalLineCount; i++) |
| | | lines[i].LowShelfEnabled = scaledValue >= 0.5; |
| | | break; |
| | | case Parameter::EqHighShelfEnabled: |
| | | for (int i = 0; i < TotalLineCount; i++) |
| | | lines[i].HighShelfEnabled = scaledValue >= 0.5; |
| | | break; |
| | | case Parameter::EqLowpassEnabled: |
| | | for (int i = 0; i < TotalLineCount; i++) |
| | | lines[i].CutoffEnabled = scaledValue >= 0.5; |
| | | break; |
| | | case Parameter::EqLowFreq: |
| | | for (int i = 0; i < TotalLineCount; i++) |
| | | lines[i].SetLowShelfFrequency(scaledValue); |
| | | break; |
| | | case Parameter::EqHighFreq: |
| | | for (int i = 0; i < TotalLineCount; i++) |
| | | lines[i].SetHighShelfFrequency(scaledValue); |
| | | break; |
| | | case Parameter::EqCutoff: |
| | | for (int i = 0; i < TotalLineCount; i++) |
| | | lines[i].SetCutoffFrequency(scaledValue); |
| | | break; |
| | | case Parameter::EqLowGain: |
| | | for (int i = 0; i < TotalLineCount; i++) |
| | | lines[i].SetLowShelfGain(scaledValue); |
| | | break; |
| | | case Parameter::EqHighGain: |
| | | for (int i = 0; i < TotalLineCount; i++) |
| | | lines[i].SetHighShelfGain(scaledValue); |
| | | break; |
| | | |
| | | |
| | | case Parameter::EqCrossSeed: |
| | | crossSeed = channelLr == ChannelLR::Right ? 0.5 * scaledValue : 1 - 0.5 * scaledValue; |
| | | multitap.SetCrossSeed(crossSeed); |
| | | diffuser.SetCrossSeed(crossSeed); |
| | | UpdateLines(); |
| | | UpdatePostDiffusion(); |
| | | break; |
| | | |
| | | |
| | | case Parameter::SeedTap: |
| | | multitap.SetSeed((int)scaledValue); |
| | | break; |
| | | case Parameter::SeedDiffusion: |
| | | diffuser.SetSeed((int)scaledValue); |
| | | break; |
| | | case Parameter::SeedDelay: |
| | | delayLineSeed = (int)scaledValue; |
| | | UpdateLines(); |
| | | break; |
| | | case Parameter::SeedPostDiffusion: |
| | | postDiffusionSeed = (int)scaledValue; |
| | | UpdatePostDiffusion(); |
| | | break; |
| | | } |
| | | } |
| | | |
| | | void Process(float* input, float* output, int bufSize) |
| | | { |
| | | float tempBuffer[BUFFER_SIZE]; |
| | | float earlyOutBuffer[BUFFER_SIZE]; |
| | | float lineOutBuffer[BUFFER_SIZE]; |
| | | float lineSumBuffer[BUFFER_SIZE]; |
| | | |
| | | Utils::Copy(tempBuffer, input, bufSize); |
| | | |
| | | if (lowCutEnabled) |
| | | highPass.Process(tempBuffer, tempBuffer, bufSize); |
| | | if (highCutEnabled) |
| | | lowPass.Process(tempBuffer, tempBuffer, bufSize); |
| | | |
| | | // completely zero if no input present |
| | | // Previously, the very small values were causing some really strange CPU spikes |
| | | for (int i = 0; i < bufSize; i++) |
| | | { |
| | | auto n = tempBuffer[i]; |
| | | if (n * n < 0.000000001) |
| | | tempBuffer[i] = 0; |
| | | } |
| | | |
| | | preDelay.Process(tempBuffer, tempBuffer, bufSize); |
| | | if (multitapEnabled) |
| | | multitap.Process(tempBuffer, tempBuffer, bufSize); |
| | | if (diffuserEnabled) |
| | | diffuser.Process(tempBuffer, tempBuffer, bufSize); |
| | | |
| | | Utils::Copy(earlyOutBuffer, tempBuffer, bufSize); |
| | | Utils::ZeroBuffer(lineSumBuffer, bufSize); |
| | | for (int i = 0; i < lineCount; i++) |
| | | { |
| | | lines[i].Process(tempBuffer, lineOutBuffer, bufSize); |
| | | Utils::Mix(lineSumBuffer, lineOutBuffer, 1.0f, bufSize); |
| | | } |
| | | |
| | | auto perLineGain = GetPerLineGain(); |
| | | Utils::Gain(lineSumBuffer, perLineGain, bufSize); |
| | | |
| | | for (int i = 0; i < bufSize; i++) |
| | | { |
| | | output[i] = dryOut * input[i] |
| | | + earlyOut * earlyOutBuffer[i] |
| | | + lineOut * lineSumBuffer[i]; |
| | | } |
| | | } |
| | | |
| | | void ClearBuffers() |
| | | { |
| | | lowPass.ClearBuffers(); |
| | | highPass.ClearBuffers(); |
| | | preDelay.ClearBuffers(); |
| | | multitap.ClearBuffers(); |
| | | diffuser.ClearBuffers(); |
| | | for (int i = 0; i < TotalLineCount; i++) |
| | | lines[i].ClearBuffers(); |
| | | } |
| | | |
| | | |
| | | private: |
| | | float GetPerLineGain() |
| | | { |
| | | return 1.0 / std::sqrt(lineCount); |
| | | } |
| | | |
| | | void UpdateLines() |
| | | { |
| | | auto lineDelaySamples = (int)Ms2Samples(paramsScaled[Parameter::LateLineSize]); |
| | | auto lineDecayMillis = paramsScaled[Parameter::LateLineDecay] * 1000; |
| | | auto lineDecaySamples = Ms2Samples(lineDecayMillis); |
| | | |
| | | auto lineModAmount = Ms2Samples(paramsScaled[Parameter::LateLineModAmount]); |
| | | auto lineModRate = paramsScaled[Parameter::LateLineModRate]; |
| | | |
| | | auto lateDiffusionModAmount = Ms2Samples(paramsScaled[Parameter::LateDiffuseModAmount]); |
| | | auto lateDiffusionModRate = paramsScaled[Parameter::LateDiffuseModRate]; |
| | | |
| | | auto delayLineSeeds = RandomBuffer::Generate(delayLineSeed, TotalLineCount * 3, crossSeed); |
| | | |
| | | for (int i = 0; i < TotalLineCount; i++) |
| | | { |
| | | auto modAmount = lineModAmount * (0.7 + 0.3 * delayLineSeeds[i]); |
| | | auto modRate = lineModRate * (0.7 + 0.3 * delayLineSeeds[TotalLineCount + i]) / samplerate; |
| | | |
| | | auto delaySamples = (0.5 + 1.0 * delayLineSeeds[TotalLineCount * 2 + i]) * lineDelaySamples; |
| | | if (delaySamples < modAmount + 2) // when the delay is set really short, and the modulation is very high |
| | | delaySamples = modAmount + 2; // the mod could actually take the delay time negative, prevent that! -- provide 2 extra sample as margin of safety |
| | | |
| | | auto dbAfter1Iteration = delaySamples / lineDecaySamples * (-60); // lineDecay is the time it takes to reach T60 |
| | | auto gainAfter1Iteration = Utils::DB2Gainf(dbAfter1Iteration); |
| | | |
| | | lines[i].SetDelay((int)delaySamples); |
| | | lines[i].SetFeedback(gainAfter1Iteration); |
| | | lines[i].SetLineModAmount(modAmount); |
| | | lines[i].SetLineModRate(modRate); |
| | | lines[i].SetDiffuserModAmount(lateDiffusionModAmount); |
| | | lines[i].SetDiffuserModRate(lateDiffusionModRate); |
| | | } |
| | | } |
| | | |
| | | void UpdatePostDiffusion() |
| | | { |
| | | for (int i = 0; i < TotalLineCount; i++) |
| | | lines[i].SetDiffuserSeed((postDiffusionSeed) * (i + 1), crossSeed); |
| | | } |
| | | |
| | | float Ms2Samples(float value) |
| | | { |
| | | return value / 1000.0f * samplerate; |
| | | } |
| | | |
| | | }; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | |
| | | #pragma once |
| | | |
| | | #include <stdio.h> |
| | | #include <vector> |
| | | #include "Parameters.h" |
| | | #include "ReverbChannel.h" |
| | | #include "AllpassDiffuser.h" |
| | | #include "MultitapDelay.h" |
| | | #include "Utils.h" |
| | | |
| | | namespace ReverbHallRoom |
| | | { |
| | | class ReverbController |
| | | { |
| | | private: |
| | | int samplerate; |
| | | |
| | | ReverbChannel channelL; |
| | | ReverbChannel channelR; |
| | | double parameters[(int)Parameter::COUNT] = {0}; |
| | | |
| | | public: |
| | | ReverbController(int samplerate = 48000) : |
| | | channelL(samplerate, ChannelLR::Left), |
| | | channelR(samplerate, ChannelLR::Right) |
| | | { |
| | | this->samplerate = samplerate; |
| | | } |
| | | |
| | | int GetSamplerate() |
| | | { |
| | | return samplerate; |
| | | } |
| | | |
| | | void SetSamplerate(int samplerate) |
| | | { |
| | | this->samplerate = samplerate; |
| | | channelL.SetSamplerate(samplerate); |
| | | channelR.SetSamplerate(samplerate); |
| | | } |
| | | |
| | | int GetParameterCount() |
| | | { |
| | | return Parameter::COUNT; |
| | | } |
| | | |
| | | double* GetAllParameters() |
| | | { |
| | | return parameters; |
| | | } |
| | | |
| | | void SetParameter(int paramId, double value) |
| | | { |
| | | parameters[paramId] = value; |
| | | auto scaled = ScaleParam(value, paramId); |
| | | channelL.SetParameter(paramId, scaled); |
| | | channelR.SetParameter(paramId, scaled); |
| | | } |
| | | |
| | | void ClearBuffers() |
| | | { |
| | | channelL.ClearBuffers(); |
| | | channelR.ClearBuffers(); |
| | | } |
| | | |
| | | void Process(float* inL, float* inR, float* outL, float* outR, int bufSize) |
| | | { |
| | | float outLTemp[BUFFER_SIZE]; |
| | | float outRTemp[BUFFER_SIZE]; |
| | | |
| | | while (bufSize > 0) |
| | | { |
| | | int subBufSize = bufSize > BUFFER_SIZE ? BUFFER_SIZE : bufSize; |
| | | ProcessChunk(inL, inR, outLTemp, outRTemp, subBufSize); |
| | | Utils::Copy(outL, outLTemp, subBufSize); |
| | | Utils::Copy(outR, outRTemp, subBufSize); |
| | | inL = &inL[subBufSize]; |
| | | inR = &inR[subBufSize]; |
| | | outL = &outL[subBufSize]; |
| | | outR = &outR[subBufSize]; |
| | | bufSize -= subBufSize; |
| | | } |
| | | } |
| | | |
| | | private: |
| | | void ProcessChunk(float* inL, float* inR, float* outL, float* outR, int bufSize) |
| | | { |
| | | float leftChannelIn[BUFFER_SIZE]; |
| | | float rightChannelIn[BUFFER_SIZE]; |
| | | |
| | | float inputMix = ScaleParam(parameters[Parameter::InputMix], Parameter::InputMix); |
| | | float cm = inputMix * 0.5; |
| | | float cmi = (1 - cm); |
| | | |
| | | for (int i = 0; i < bufSize; i++) |
| | | { |
| | | leftChannelIn[i] = inL[i] * cmi + inR[i] * cm; |
| | | rightChannelIn[i] = inR[i] * cmi + inL[i] * cm; |
| | | } |
| | | |
| | | channelL.Process(leftChannelIn, outL, bufSize); |
| | | channelR.Process(rightChannelIn, outR, bufSize); |
| | | } |
| | | }; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | |
| | | #pragma once |
| | | |
| | | #define _USE_MATH_DEFINES 1 |
| | | #include <math.h> |
| | | #include <stdint.h> |
| | | |
| | | namespace ReverbHallRoom |
| | | { |
| | | namespace Utils |
| | | { |
| | | template<typename T> |
| | | inline void ZeroBuffer(T* buffer, int len) |
| | | { |
| | | for (int i = 0; i < len; i++) |
| | | buffer[i] = 0; |
| | | } |
| | | |
| | | template<typename T> |
| | | inline void Copy(T* dest, T* source, int len) |
| | | { |
| | | memcpy(dest, source, len * sizeof(T)); |
| | | } |
| | | |
| | | template<typename T> |
| | | inline void Gain(T* buffer, T gain, int len) |
| | | { |
| | | for (int i = 0; i < len; i++) |
| | | { |
| | | buffer[i] *= gain; |
| | | } |
| | | } |
| | | |
| | | template<typename T> |
| | | inline void Mix(T* target, T* source, T gain, int len) |
| | | { |
| | | for (int i = 0; i < len; i++) |
| | | target[i] += source[i] * gain; |
| | | } |
| | | |
| | | inline float DB2Gainf(float input) |
| | | { |
| | | //return std::pow(10.0f, input / 20.0f); |
| | | return powf(10, input * 0.05f); |
| | | } |
| | | |
| | | template<typename T> |
| | | inline double DB2Gain(T input) |
| | | { |
| | | return pow10f(input / 20.0); |
| | | } |
| | | |
| | | template<typename T> |
| | | inline double Gain2DB(T input) |
| | | { |
| | | //if (input < 0.0000001) |
| | | // return -100000; |
| | | |
| | | return 20.0f * log10f(input); |
| | | } |
| | | |
| | | const float dec1Mult = (10 / 9.0) * 0.1; |
| | | const float dec2Mult = (100 / 99.0) * 0.01; |
| | | const float dec3Mult = (1000 / 999.0) * 0.001; |
| | | const float dec4Mult = (10000 / 9999.0) * 0.0001; |
| | | |
| | | const float oct1Mult = (2 / 1.0) * 0.5; |
| | | const float oct2Mult = (4 / 3.0) * 0.25; |
| | | const float oct3Mult = (8 / 7.0) * 0.125; |
| | | const float oct4Mult = (16 / 15.0) * 0.0625; |
| | | const float oct5Mult = (32 / 31.0) * 0.03125; |
| | | const float oct6Mult = (64 / 63.0) * 0.015625; |
| | | const float oct7Mult = (128 / 127.0) * 0.0078125; |
| | | const float oct8Mult = (256 / 255.0) * 0.00390625; |
| | | |
| | | inline float Resp1dec(float x) { return (powf(10, x) - 1) * dec1Mult; } |
| | | inline float Resp2dec(float x) { return (powf(10, 2 * x) - 1) * dec2Mult; } |
| | | inline float Resp3dec(float x) { return (powf(10, 3 * x) - 1) * dec3Mult; } |
| | | inline float Resp4dec(float x) { return (powf(10, 4 * x) - 1) * dec4Mult; } |
| | | |
| | | inline float Resp1oct(float x) { return (powf(2, x) - 1) * oct1Mult; } |
| | | inline float Resp2oct(float x) { return (powf(2, 2 * x) - 1) * oct2Mult; } |
| | | inline float Resp3oct(float x) { return (powf(2, 3 * x) - 1) * oct3Mult; } |
| | | inline float Resp4oct(float x) { return (powf(2, 4 * x) - 1) * oct4Mult; } |
| | | inline float Resp5oct(float x) { return (powf(2, 5 * x) - 1) * oct5Mult; } |
| | | inline float Resp6oct(float x) { return (powf(2, 6 * x) - 1) * oct6Mult; } |
| | | inline float Resp7oct(float x) { return (powf(2, 7 * x) - 1) * oct7Mult; } |
| | | inline float Resp8oct(float x) { return (powf(2, 8 * x) - 1) * oct8Mult; } |
| | | |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #include "reverb.h" |
| | | //#include "reverb_wrapper.h" |
| | | #include <stdio.h> |
| | | |
| | | |
| | | static int ch,n,L; |
| | | static float *x[32], *y[32]; |
| | | |
| | | |
| | | void reverb_wrapper_init(void **p, int channels, int frame_size, int sample_rate, double dry, double early, double late, int input_mix_on, int hight_cut_on, // 6 |
| | | int low_cut_on, double input_mix, double high_cut_freq, double low_cut_freq, double cross_seed, int taps_on, double taps_count, double taps_pre_delay, double taps_decay, double taps_length, int early_difus_on, double early_difus_count, double early_difus_delay, // 13 |
| | | double early_difus_feedback, double early_difus_mod_amt, double early_difus_mod_rate, int late_mode, int late_reflect_on, double late_line_count, double late_line_size, double late_line_mod_amt, double late_line_decay, double late_line_mod_rate, double late_difus_count, double late_difus_delay, // 12 |
| | | double late_difus_feedback, double late_difus_mod_amt, double late_difus_mod_rate, int eq_low_shelf_on, int eq_high_shelf_on, int eq_low_pass_on, double eq_low_shelf_freq, double eq_low_shelf_gain, double eq_high_shelf_freq, double eq_high_shelf_gain, double eq_low_pass_freq // 11 |
| | | ) |
| | | { |
| | | Reverb_common c_t = {sample_rate, dry, early, late, input_mix_on, hight_cut_on, low_cut_on, input_mix, high_cut_freq, low_cut_freq, cross_seed}; |
| | | Reverb_taps t_t = {taps_on, taps_count, taps_pre_delay, taps_decay, taps_length}; |
| | | Reverb_early e_t = {early_difus_on, early_difus_count, early_difus_delay, early_difus_feedback, early_difus_mod_amt, early_difus_mod_rate}; |
| | | Reverb_late l_t = {late_mode, late_reflect_on, late_line_count, late_line_size, late_line_mod_amt, late_line_decay, late_line_mod_rate, late_difus_count, late_difus_delay, late_difus_feedback, late_difus_mod_amt, late_difus_mod_rate}; |
| | | Reverb_eq eq_t = {eq_low_shelf_on, eq_high_shelf_on, eq_low_pass_on, eq_low_shelf_freq, eq_low_shelf_gain, eq_high_shelf_freq, eq_high_shelf_gain, eq_low_pass_freq}; |
| | | |
| | | *(Reverb **)p = reverb_new(channels, frame_size, &c_t, &t_t, &e_t, &l_t, &eq_t); |
| | | ch = channels; |
| | | n = frame_size; |
| | | |
| | | // FILE *file = fopen("debug.txt", "w"); |
| | | // if (NULL == file) return; |
| | | |
| | | // fprintf(file, "GUI params:\n"); |
| | | // fprintf(file, "late_refl_on:%d.\n", l_t.late_reflect_on); |
| | | // fprintf(file, "FS:%d dry:%2.2f early:%2.2f late:%2.2f inp_on:%d h_c_on:%d l_c_on:%d in_mix:%2.2f h_c:%2.2f l_c:%2.2f c_s:%2.2f.\n", |
| | | // c_t.sample_rate, c_t.dry, c_t.early, c_t.late, c_t.input_mix_on, c_t.high_cut_on, \ |
| | | // c_t.low_cut_on, c_t.input_mix, c_t.high_cut, c_t.low_cut, c_t.cross_seed); |
| | | // fclose(file); |
| | | } |
| | | |
| | | |
| | | void reverb_wrapper_process(void *p, /*int sample_rate, double dry, double early, double late, int input_mix_on, int hight_cut_on, // 6 |
| | | int low_cut_on, double input_mix, double high_cut_freq, double low_cut_freq, double cross_seed, int taps_on, double taps_count, double taps_pre_delay, double taps_decay, double taps_length, int early_difus_on, double early_difus_count, double early_difus_delay, // 13 |
| | | double early_difus_feedback, double early_difus_mod_amt, double early_difus_mod_rate, int late_mode, int late_reflect_on, double late_line_count, double late_line_size, double late_line_mod_amt, double late_line_decay, double late_line_mod_rate, double late_difus_count, double late_difus_delay, // 12 |
| | | double late_difus_feedback, double late_difus_mod_amt, double late_difus_mod_rate, int eq_low_shelf_on, int eq_high_shelf_on, int eq_low_pass_on, double eq_low_shelf_freq, double eq_low_shelf_gain, double eq_high_shelf_freq, double eq_high_shelf_gain, double eq_low_pass_freq, |
| | | */float *src, float *dst) |
| | | { |
| | | int i; |
| | | |
| | | for(i = 0; i < ch; i ++) |
| | | x[i] = src + i * n; |
| | | |
| | | for(i = 0; i < ch; i ++) |
| | | y[i] = dst + i * n; |
| | | |
| | | |
| | | reverb_process(p, x, y); |
| | | |
| | | /*Reverb params = {ch, n, {sample_rate, dry, early, late, input_mix_on, hight_cut_on, low_cut_on, input_mix, high_cut_freq, low_cut_freq, cross_seed}, |
| | | {taps_on, taps_count, taps_pre_delay, taps_decay, taps_length}, |
| | | {early_difus_on, early_difus_count, early_difus_delay, early_difus_feedback, early_difus_mod_amt, early_difus_mod_rate}, |
| | | {late_mode, late_reflect_on, late_line_count, late_line_size, late_line_mod_amt, late_line_mod_rate}, |
| | | {eq_low_shelf_on, eq_high_shelf_on, eq_low_pass_on, eq_low_shelf_freq, eq_low_shelf_gain, eq_high_shelf_freq, eq_high_shelf_gain, eq_low_pass_freq}, |
| | | }; |
| | | reverb_params_set(¶ms);*/ |
| | | |
| | | } |
| | | |
| | | |
| | | void reverb_wrapper_delete(void *p) |
| | | { |
| | | reverb_delete(p); |
| | | } |
| | | |
| | | |
| | | |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #ifndef REVERB_WRAPPER_H |
| | | #define REVERB_WRAPPER_H |
| | | |
| | | |
| | | #define UI_FULL 0 |
| | | #define UI_XYK 1 |
| | | #define GUI UI_FULL |
| | | |
| | | |
| | | #ifdef __cplusplus |
| | | extern "C" { |
| | | #endif |
| | | |
| | | |
| | | #if (GUI == UI_XYK) |
| | | |
| | | void reverb_wrapper_init(void **p, int channels, int frame_size, int sample_rate, double dry, double early, double late, int input_mix_on, int hight_cut_on, // 1~6 |
| | | int low_cut_on, double in_mix, double high_cut_freq, double low_cut_freq, double cross_seed, int taps_on, double taps_count, double taps_pre_delay, double taps_decay, double taps_length, int early_difus_on, double early_difus_count, double early_difus_delay, // 7~19 |
| | | double early_difus_feedback, double early_difus_mod_amt, double early_difus_mod_rate, int late_mode, int late_reflect_on, double late_line_count, double late_line_size, double late_line_mod_amt, double late_line_decay, double late_line_mod_rate, double late_difus_count, double late_difus_delay, // 20~31 |
| | | double late_difus_feedback, double late_difus_mod_amt, double late_difus_mod_rate, int eq_low_shelf_on, int eq_high_shelf_on, int eq_low_pass_on, double eq_low_shelf_freq, double eq_low_shelf_gain, double eq_high_shelf_freq, double eq_high_shelf_gain, double eq_low_pass_freq //32~42 |
| | | ); |
| | | |
| | | void reverb_wrapper_process(void *p, int sample_rate, double dry, double early, double late, int input_mix_on, int hight_cut_on, // 6 |
| | | int low_cut_on, double input_mix, double high_cut_freq, double low_cut_freq, double cross_seed, int taps_on, double taps_count, double taps_pre_delay, double taps_decay, double taps_length, int early_difus_on, double early_difus_count, double early_difus_delay, // 13 |
| | | double early_difus_feedback, double early_difus_mod_amt, double early_difus_mod_rate, int late_mode, int late_reflect_on, double late_line_count, double late_line_size, double late_line_mod_amt, double late_line_decay, double late_line_mod_rate, double late_difus_count, double late_difus_delay, // 12 |
| | | double late_difus_feedback, double late_difus_mod_amt, double late_difus_mod_rate, int eq_low_shelf_on, int eq_high_shelf_on, int eq_low_pass_on, double eq_low_shelf_freq, double eq_low_shelf_gain, double eq_high_shelf_freq, double eq_high_shelf_gain, double eq_low_pass_freq, |
| | | float *src, float *dst); |
| | | |
| | | #else |
| | | |
| | | void reverb_wrapper_init(void **p, int channels, int frame_size, int sample_rate, double dry, double early, double late, int input_mix_on, int hight_cut_on, // 1~6 |
| | | int low_cut_on, double in_mix, double high_cut_freq, double low_cut_freq, double cross_seed, int taps_on, double taps_count, double taps_pre_delay, double taps_decay, double taps_length, int early_difus_on, double early_difus_count, double early_difus_delay, // 7~19 |
| | | double early_difus_feedback, double early_difus_mod_amt, double early_difus_mod_rate, int late_mode, int late_reflect_on, double late_line_count, double late_line_size, double late_line_mod_amt, double late_line_decay, double late_line_mod_rate, double late_difus_count, double late_difus_delay, // 20~31 |
| | | double late_difus_feedback, double late_difus_mod_amt, double late_difus_mod_rate, int eq_low_shelf_on, int eq_high_shelf_on, int eq_low_pass_on, double eq_low_shelf_freq, double eq_low_shelf_gain, double eq_high_shelf_freq, double eq_high_shelf_gain, double eq_low_pass_freq //32~42 |
| | | ); |
| | | |
| | | void reverb_wrapper_process(void *p, /*int sample_rate, double dry, double early, double late, int input_mix_on, int hight_cut_on, // 6 |
| | | int low_cut_on, double input_mix, double high_cut_freq, double low_cut_freq, double cross_seed, int taps_on, double taps_count, double taps_pre_delay, double taps_decay, double taps_length, int early_difus_on, double early_difus_count, double early_difus_delay, // 13 |
| | | double early_difus_feedback, double early_difus_mod_amt, double early_difus_mod_rate, int late_mode, int late_reflect_on, double late_line_count, double late_line_size, double late_line_mod_amt, double late_line_decay, double late_line_mod_rate, double late_difus_count, double late_difus_delay, // 12 |
| | | double late_difus_feedback, double late_difus_mod_amt, double late_difus_mod_rate, int eq_low_shelf_on, int eq_high_shelf_on, int eq_low_pass_on, double eq_low_shelf_freq, double eq_low_shelf_gain, double eq_high_shelf_freq, double eq_high_shelf_gain, double eq_low_pass_freq, |
| | | */float *src, float *dst); |
| | | |
| | | #endif |
| | | |
| | | void reverb_wrapper_delete(void *p); |
| | | |
| | | |
| | | |
| | | |
| | | #endif |
| | | |
| | | |
| | | |
| | | |
| | | #ifdef __cplusplus |
| | | } |
| | | #endif |