Hi
After I have made an intermediate sound ~ one that is used in several places, I want to delete it.
This is to free up my remaining memory for more things I need to do.
Is it enough to just assign it to something like: (s-rest .001)
Would that be enough?
Or should I use something like what is done in Clean-Scratch:
(defun clean-scratch ()
(if (boundp 'scratch)
(setq scratch 'unbound))
(do ((plist (symbol-plist 'scratch)(symbol-plist 'scratch)))
((not plist))
(remprop 'scratch (first plist))))
If so how much of that process need I apply to some sound of mine ~ say “my-sound”
And what would it look like for an array vs a mono sound?
Thanks,
~ Dalagar
That depends on the rest of the code.
The data might still be bound to another symbol, or might be still be captured in a closure, in which case the data would still exist and occupy memory.
I don’t think there are easy answers to the issue of freeing memory, though careful attention to the manual can help. For example, notice that in the description of PEAK
since the variable retains a reference to the sound, the sound will be evaluated and left in memory.
However, if you try it, you should see that it still uses around 700 MB!
The reason is because the symbol PK points to (peak sig ny:all) so it is indirectly referencing SIG which has around 700 MB of data. Because there is still a reference to that data, the data remains in memory until PK is destroyed.
The solution in this case is to avoid binding the sound to a variable so that it can be garbage collected while PEAK is calculating the peak level.
Yup,
Avoid binding a sound to a variable outside of a “let” seems to be the solution to the problem.
Easy to fix, but it makes the code less readable to me when I revisit it later.
Binding things, allows me to thereby name them…
Would using the (defmac (~~) ~~~~) construct to allow naming or some other trick make my code less painful for others to read?
I guess more violations of the indenting rules, and excessive comments are mandated in this situation.
This fact shall make me reluctant to share my code with others out of pure embarrassment.
Thanks, Steve, your answers work!
~ Dalagar
In the example above, we “could” have bound the sound returned from “mysound” to a variable, such as: (setf my-new-sound (mysound dur))
but we don’t want to do that because it would prevent the sound from being garbage collected until all references to the sound are released. Instead, we just use the function (mysound ) directly, and it is still obvious that we’re dealing with a generated sound.
Optionally we could add a brief comment to say why we are generating the sound twice:
(setf dur 3600)
(defun mysound (dur)
(stretch-abs dur (sum (hzosc 441)(hzosc 480))))
(let ((pk (peak (mysound dur) ny:all)))
; generate the sound again because we don't want to hang onto the sound in ram.
(mult (/ pk) (mysound dur)))
but I don’t think that is really necessary.
Another common practice is to include a comment, either directly before a function declaration:
;;; Return a sound of length 'dur'.
(defun mysound (dur)
(stretch-abs dur (sum (hzosc 441)(hzosc 480))))
or directly after the function declaration:
(defun mysound (dur)
;;; Return a sound of length 'dur'.
(stretch-abs dur (sum (hzosc 441)(hzosc 480))))
The former is used in Nyquist’s source code, but I generally prefer the latter as it ensures that the comment stays next to the code that it refers to, even if the function is moved to a different position in the code.