Skip to content

Commit

Permalink
Version bumps.
Browse files Browse the repository at this point in the history
  • Loading branch information
BleuBleu committed Jan 17, 2025
1 parent f45e248 commit 0178b59
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 128 deletions.
6 changes: 6 additions & 0 deletions Docs/docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ Version history / release notes for each release.

To download older versions or view the release dates, please visit the [Github Releases](https://github.com/BleuBleu/FamiStudio/releases) page.

## Version 4.3.2 (Hotfix)

Changes/Fixes:

* Fixed crash when exporting audio/video

## Version 4.3.1 (Hotfix)

Changes/Fixes:
Expand Down
2 changes: 1 addition & 1 deletion FamiStudio/Properties/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="58" android:versionName="4.3.1" package="org.famistudio" android:installLocation="auto">
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="59" android:versionName="4.3.2" package="org.famistudio" android:installLocation="auto">
<uses-sdk android:minSdkVersion="26" android:targetSdkVersion="34" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
Expand Down
4 changes: 2 additions & 2 deletions FamiStudio/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@

// The last digit is the BETA version number. When it is non-zero, the build and will be
// interpreted as a development version.
[assembly: AssemblyVersion("4.3.1.0")]
[assembly: AssemblyFileVersion("4.3.1.0")]
[assembly: AssemblyVersion("4.3.2.0")]
[assembly: AssemblyFileVersion("4.3.2.0")]

#if FAMISTUDIO_ANDROID
// Add some common permissions, these can be removed if not needed
Expand Down
4 changes: 2 additions & 2 deletions FamiStudio/Source/App/Droid/FamiStudioWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -786,7 +786,7 @@ public override bool OnTouchEvent(MotionEvent e)
{
if (!IsAsyncFileActivityInProgress)
{
Debug.WriteLine($"OnTouchEvent {e.Action.ToString()} ({e.GetX()}, {e.GetY()})");
//Debug.WriteLine($"OnTouchEvent {e.Action.ToString()} ({e.GetX()}, {e.GetY()})");

if (e.Action == MotionEventActions.Up)
{
Expand Down Expand Up @@ -832,7 +832,7 @@ public bool OnDown(MotionEvent e)
{
if (!IsAsyncFileActivityInProgress)
{
Debug.WriteLine($"OnDown {e.PointerCount} ({e.GetX()}, {e.GetY()})");
//Debug.WriteLine($"OnDown {e.PointerCount} ({e.GetX()}, {e.GetY()})");
lock (renderLock)
{
var ctrl = GetCapturedControlAtCoord((int)e.GetX(), (int)e.GetY(), out var x, out var y);
Expand Down
241 changes: 123 additions & 118 deletions FamiStudio/Source/Project/Project.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1970,175 +1970,180 @@ public unsafe bool AutoAssignN163WavePositions(out Dictionary<int, int> wavePosi
return true;
}

var numN163Instruments = instruments.Count(i => i.IsN163);
var numN163AutoPos = instruments.Count(i => i.IsN163 && i.N163WaveAutoPos);

if (numN163AutoPos == 0)
{
wavePositions = null;
return true;
}
// HACK : Last minute hack, when exporting we spawn multiple WavPlayer threads and
// those may end up all in this functions.
lock (this)
{
var numN163Instruments = instruments.Count(i => i.IsN163);
var numN163AutoPos = instruments.Count(i => i.IsN163 && i.N163WaveAutoPos);

if (numN163AutoPos == 0)
{
wavePositions = null;
return true;
}

//var A = Platform.TimeSeconds();
//var A = Platform.TimeSeconds();

const int numBitsPerLong = sizeof(ulong) * 8;
const int numBitsPerLong = sizeof(ulong) * 8;

var instrumentOverlaps = new Dictionary<Instrument, HashSet<Instrument>>(numN163AutoPos);
var instrumentOverlaps = new Dictionary<Instrument, HashSet<Instrument>>(numN163AutoPos);

foreach (var song in songs)
{
var numFrames = song.EndLocation.ToAbsoluteNoteIndex(song);
var numLongs = Utils.DivideAndRoundUp(numFrames, numBitsPerLong);
var instrumentMasks = new Dictionary<Instrument, N163Mask>(numN163Instruments);

// Buld a huge bitmask that tells us which frame each instrument is used.
// This is a bit overkill, but is very simple.
for (var i = 0; i < expansionNumN163Channels; i++)
foreach (var song in songs)
{
var channel = song.GetChannelByType(ChannelType.N163Wave1 + i);
var numFrames = song.EndLocation.ToAbsoluteNoteIndex(song);
var numLongs = Utils.DivideAndRoundUp(numFrames, numBitsPerLong);
var instrumentMasks = new Dictionary<Instrument, N163Mask>(numN163Instruments);

// TODO : This ignores FamiTracker delayed cuts, so it may generate sub-optimal results when they are used.
for (var it = channel.GetSparseNoteIterator(song.StartLocation, song.EndLocation, NoteFilter.Musical); !it.Done; it.Next())
// Buld a huge bitmask that tells us which frame each instrument is used.
// This is a bit overkill, but is very simple.
for (var i = 0; i < expansionNumN163Channels; i++)
{
var note = it.Note;
var channel = song.GetChannelByType(ChannelType.N163Wave1 + i);

if (note.Instrument != null)
// TODO : This ignores FamiTracker delayed cuts, so it may generate sub-optimal results when they are used.
for (var it = channel.GetSparseNoteIterator(song.StartLocation, song.EndLocation, NoteFilter.Musical); !it.Done; it.Next())
{
if (!instrumentMasks.TryGetValue(note.Instrument, out var mask))
var note = it.Note;

if (note.Instrument != null)
{
mask = new N163Mask(numLongs);
instrumentMasks.Add(note.Instrument, mask);
}
if (!instrumentMasks.TryGetValue(note.Instrument, out var mask))
{
mask = new N163Mask(numLongs);
instrumentMasks.Add(note.Instrument, mask);
}

// Start + end of this note, in frame.
var idx1 = it.Location.ToAbsoluteNoteIndex(song);
var idx2 = Math.Min(idx1 + Math.Min(note.Duration, it.DistanceToNextNote), numFrames - 1);
// Start + end of this note, in frame.
var idx1 = it.Location.ToAbsoluteNoteIndex(song);
var idx2 = Math.Min(idx1 + Math.Min(note.Duration, it.DistanceToNextNote), numFrames - 1);

var long1 = idx1 / numBitsPerLong;
var long2 = idx2 / numBitsPerLong;
var bit1 = idx1 % numBitsPerLong;
var bit2 = idx2 % numBitsPerLong;
var long1 = idx1 / numBitsPerLong;
var long2 = idx2 / numBitsPerLong;
var bit1 = idx1 % numBitsPerLong;
var bit2 = idx2 % numBitsPerLong;

var mask1 = ~((1ul << bit1) - 1ul);
var mask2 = ((1ul << bit2) - 1ul);
var mask1 = ~((1ul << bit1) - 1ul);
var mask2 = ((1ul << bit2) - 1ul);

mask.MinIndex = Math.Min(long1, mask.MinIndex);
mask.MaxIndex = Math.Max(long2, mask.MaxIndex);
mask.MinIndex = Math.Min(long1, mask.MinIndex);
mask.MaxIndex = Math.Max(long2, mask.MaxIndex);

if (long1 == long2)
{
mask.Bits[long1] |= (mask1 & mask2);
}
else
{
mask.Bits[long1] |= mask1;
mask.Bits[long2] |= mask2;
if (long1 == long2)
{
mask.Bits[long1] |= (mask1 & mask2);
}
else
{
mask.Bits[long1] |= mask1;
mask.Bits[long2] |= mask2;

for (var j = long1 + 1; j < long2; j++)
mask.Bits[j] = ulong.MaxValue;
for (var j = long1 + 1; j < long2; j++)
mask.Bits[j] = ulong.MaxValue;
}
}
}
}
}

// Then "AND" these masks to figure out which instruments overlap, update the map of overlaps.
// We create overlaps both ways, so this is O(N^2/2) i guess.
var it1 = instrumentMasks.GetEnumerator();
while (it1.MoveNext())
{
var inst1 = it1.Current.Key;
var mask1 = it1.Current.Value;

var it2 = it1;
while (it2.MoveNext())
// Then "AND" these masks to figure out which instruments overlap, update the map of overlaps.
// We create overlaps both ways, so this is O(N^2/2) i guess.
var it1 = instrumentMasks.GetEnumerator();
while (it1.MoveNext())
{
var inst2 = it2.Current.Key;
var mask2 = it2.Current.Value;
var inst1 = it1.Current.Key;
var mask1 = it1.Current.Value;

if ((inst1.N163WaveAutoPos || inst2.N163WaveAutoPos) &&
(mask1.MaxIndex >= mask1.MinIndex) &&
(mask2.MaxIndex >= mask2.MinIndex))
var it2 = it1;
while (it2.MoveNext())
{
var idx1 = Math.Max(mask1.MinIndex, mask2.MinIndex);
var idx2 = Math.Min(mask1.MaxIndex, mask2.MaxIndex);
var inst2 = it2.Current.Key;
var mask2 = it2.Current.Value;

for (var i = idx1; i <= idx2; i++)
if ((inst1.N163WaveAutoPos || inst2.N163WaveAutoPos) &&
(mask1.MaxIndex >= mask1.MinIndex) &&
(mask2.MaxIndex >= mask2.MinIndex))
{
if ((mask1.Bits[i] & mask2.Bits[i]) != 0)
var idx1 = Math.Max(mask1.MinIndex, mask2.MinIndex);
var idx2 = Math.Min(mask1.MaxIndex, mask2.MaxIndex);

for (var i = idx1; i <= idx2; i++)
{
if (inst1.N163WaveAutoPos)
if ((mask1.Bits[i] & mask2.Bits[i]) != 0)
{
if (!instrumentOverlaps.TryGetValue(inst1, out var set1))
if (inst1.N163WaveAutoPos)
{
set1 = new HashSet<Instrument>(numN163Instruments);
instrumentOverlaps.Add(inst1, set1);
if (!instrumentOverlaps.TryGetValue(inst1, out var set1))
{
set1 = new HashSet<Instrument>(numN163Instruments);
instrumentOverlaps.Add(inst1, set1);
}
set1.Add(inst2);
}
set1.Add(inst2);
}
if (inst2.N163WaveAutoPos)
{
if (!instrumentOverlaps.TryGetValue(inst2, out var set2))
if (inst2.N163WaveAutoPos)
{
set2 = new HashSet<Instrument>(numN163Instruments);
instrumentOverlaps.Add(inst2, set2);
if (!instrumentOverlaps.TryGetValue(inst2, out var set2))
{
set2 = new HashSet<Instrument>(numN163Instruments);
instrumentOverlaps.Add(inst2, set2);
}
set2.Add(inst1);
}
set2.Add(inst1);
break;
}
break;
}
}
}
}
}
}

// Finally, try to assign the wave positions without generating overlap.
// TODO : Sort instrument by descending wav size + how much they are used maybe?
wavePositions = new Dictionary<int, int>(numN163AutoPos);
// Finally, try to assign the wave positions without generating overlap.
// TODO : Sort instrument by descending wav size + how much they are used maybe?
wavePositions = new Dictionary<int, int>(numN163AutoPos);

var maxPos = N163WaveRAMSize * 2;
var overlapDetected = false;

foreach (var kv in instrumentOverlaps)
{
var inst1 = kv.Key;
var pos1 = 0;
var overlapInstruments = kv.Value;
var maxPos = N163WaveRAMSize * 2;
var overlapDetected = false;

foreach (var inst2 in overlapInstruments)
foreach (var kv in instrumentOverlaps)
{
var pos2 = (int)inst2.N163WavePos;
var inst1 = kv.Key;
var pos1 = 0;
var overlapInstruments = kv.Value;

// No position assigned yet, will be done later.
if (inst2.N163WaveAutoPos && !wavePositions.TryGetValue(inst2.Id, out pos2))
foreach (var inst2 in overlapInstruments)
{
continue;
}
var pos2 = (int)inst2.N163WavePos;

// If overlap, try again right after this instrument.
if (pos1 + inst1.N163WaveSize > pos2 &&
pos2 + inst2.N163WaveSize > pos1)
{
pos1 = pos2 + inst2.N163WaveSize;
// No position assigned yet, will be done later.
if (inst2.N163WaveAutoPos && !wavePositions.TryGetValue(inst2.Id, out pos2))
{
continue;
}

// Was not able to allocate.
if (pos1 + inst1.N163WaveSize > maxPos)
// If overlap, try again right after this instrument.
if (pos1 + inst1.N163WaveSize > pos2 &&
pos2 + inst2.N163WaveSize > pos1)
{
Log.LogMessage(LogSeverity.Warning, $"Not able to assign a N163 wave position to instrument '{inst1.Name}', reduce wave size or minimize overlap with other instruments. Setting to 0.");
pos1 = 0;
overlapDetected = true;
break;
pos1 = pos2 + inst2.N163WaveSize;

// Was not able to allocate.
if (pos1 + inst1.N163WaveSize > maxPos)
{
Log.LogMessage(LogSeverity.Warning, $"Not able to assign a N163 wave position to instrument '{inst1.Name}', reduce wave size or minimize overlap with other instruments. Setting to 0.");
pos1 = 0;
overlapDetected = true;
break;
}
}
}
}

wavePositions.Add(inst1.Id, pos1);
}
wavePositions.Add(inst1.Id, pos1);
}

//var B = Platform.TimeSeconds();
//Trace.WriteLine($"ASSIGN TIME! {(B - A) * 1000} ms");
//var B = Platform.TimeSeconds();
//Trace.WriteLine($"ASSIGN TIME! {(B - A) * 1000} ms");

return !overlapDetected;
return !overlapDetected;
}
}

public int FindLargestUniqueId()
Expand Down
8 changes: 4 additions & 4 deletions Setup/Setup.vdproj
Original file line number Diff line number Diff line change
Expand Up @@ -1086,15 +1086,15 @@
{
"Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:FamiStudio"
"ProductCode" = "8:{358D062E-06E8-41C1-ADAB-5B70CC8F3E89}"
"PackageCode" = "8:{C5925232-0F9F-4BB0-9526-CD51C16F9301}"
"ProductCode" = "8:{837BBC62-64A8-4FF9-9485-A8EFC6F7E7C9}"
"PackageCode" = "8:{7861A106-E418-42EF-A8CC-E2B106B95C5B}"
"UpgradeCode" = "8:{B82EE4DC-4ECE-46C8-A464-1B7CAE09B938}"
"AspNetVersion" = "8:4.0.30319.0"
"RestartWWWService" = "11:FALSE"
"RemovePreviousVersions" = "11:TRUE"
"DetectNewerInstalledVersion" = "11:TRUE"
"InstallAllUsers" = "11:FALSE"
"ProductVersion" = "8:4.3.1"
"ProductVersion" = "8:4.3.2"
"Manufacturer" = "8:BleuBleu"
"ARPHELPTELEPHONE" = "8:"
"ARPHELPLINK" = "8:https://famistudio.org/doc/install/"
Expand Down Expand Up @@ -1664,7 +1664,7 @@
}
"{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_9A9A290F02BD4DF9857CA1EFF73548B4"
{
"SourcePath" = "8:..\\FamiStudio\\obj\\Release\\net8.0\\apphost.exe"
"SourcePath" = "8:..\\FamiStudio\\obj\\Debug\\net8.0\\apphost.exe"
"TargetName" = "8:"
"Tag" = "8:"
"Folder" = "8:_35E89725F8BA48E0AC14F44C8E513BED"
Expand Down
2 changes: 1 addition & 1 deletion Setup/Version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
431
432

0 comments on commit 0178b59

Please sign in to comment.